Compare commits

...

15 Commits

Author SHA1 Message Date
Andy Bitz
94483c8b36 Publish Stable
- @vercel/static-build@0.17.15
2020-11-10 21:32:13 +01:00
Andy Bitz
078f9de44e Publish Canary
- @vercel/frameworks@0.1.2-canary.2
 - @vercel/build-utils@2.5.5-canary.3
 - vercel@20.1.3-canary.7
 - @vercel/client@9.0.4-canary.4
 - @vercel/static-build@0.17.15-canary.0
 - @vercel/redwood@0.1.2-canary.2
2020-11-10 21:18:48 +01:00
Andy
0ae41f97a4 [static-build] Ignore framework routes if config/routes.json is present (#5401) 2020-11-10 21:17:45 +01:00
Nathan Rajlich
9fb6a1ec4c [frameworks] Use "value" instead of "placeholder" for frameworks with known installCommand (#5400) 2020-11-10 11:25:16 -08:00
Andy Bitz
21be46c8bb Publish Stable
- @vercel/static-build@0.17.14
2020-11-10 18:51:06 +01:00
Andy
91942fc4d2 [static-build] Expect routes array directly (#5399) 2020-11-10 18:49:51 +01:00
Andy Bitz
8e02f2289f Publish Stable
- @vercel/static-build@0.17.13
2020-11-10 16:21:58 +01:00
Andy Bitz
4205d643a1 Publish Canary
- @vercel/next@2.6.39-canary.0
 - @vercel/static-build@0.17.13-canary.0
2020-11-10 16:19:08 +01:00
Andy
b2dda4dbb9 [static-build] Support static and config directory in .vercel_build_output (#5396)
* Handle routes and static files from the build output directory

* Add logging

* Move comment
2020-11-10 16:18:07 +01:00
Joe Haddad
f36eac3d0a [next] files within the buildId directory are immutable (#5386)
Co-authored-by: Tim Neutkens <tim@timneutkens.nl>
2020-11-10 09:19:26 -05:00
Andy Bitz
a2c56425f4 Publish Stable
- @vercel/static-build@0.17.12
2020-11-10 00:43:05 +01:00
Andy Bitz
c759bfda9c Publish Canary
- @vercel/client@9.0.4-canary.3
 - @vercel/static-build@0.17.12-canary.0
2020-11-10 00:14:31 +01:00
Andy
57995001ac [static-build] Add directory for Serverless Functions (#5390)
* [@vercel/static-build] Add directory for Serverless Functions

* Update tests and only consider index.js files

* Import only once

* Only change for zeroConfig

* Update packages/now-static-build/src/utils/_shared.ts

Co-authored-by: Steven <steven@ceriously.com>

* Update packages/now-static-build/test/fixtures/62-function-output-directory-with-static/now.json

Co-authored-by: Steven <steven@ceriously.com>

* Update packages/now-static-build/test/fixtures/61-function-output-directory/now.json

Co-authored-by: Steven <steven@ceriously.com>

* Update build

* Fix type

* Remove line

* Add to .vercelignore

* Fix paths in test

* Move more files

* Remove special case for test

Co-authored-by: Steven <steven@ceriously.com>
2020-11-10 00:09:23 +01:00
Nathan Rajlich
e5553d8ec2 Publish Canary
- @vercel/build-utils@2.5.5-canary.2
 - vercel@20.1.3-canary.6
 - @vercel/client@9.0.4-canary.2
2020-11-09 15:02:17 -08:00
Nathan Rajlich
dcee5b16c7 [build-utils] Add installCommand to Config object (#5391) 2020-11-09 22:27:29 +00:00
44 changed files with 427 additions and 39 deletions

View File

@@ -849,7 +849,7 @@
},
"settings": {
"installCommand": {
"placeholder": "`bundle install`"
"value": "bundle install"
},
"buildCommand": {
"placeholder": "`npm run build` or `jekyll build`"
@@ -909,7 +909,7 @@
},
"settings": {
"installCommand": {
"placeholder": "`bundle install`"
"value": "bundle install"
},
"buildCommand": {
"value": "`npm run build` or `bundle exec middleman build`"

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/frameworks",
"version": "0.1.2-canary.1",
"version": "0.1.2-canary.2",
"main": "frameworks.json",
"license": "UNLICENSED",
"scripts": {

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/build-utils",
"version": "2.5.5-canary.1",
"version": "2.5.5-canary.3",
"license": "MIT",
"main": "./dist/index.js",
"types": "./dist/index.d.js",
@@ -29,7 +29,7 @@
"@types/node-fetch": "^2.1.6",
"@types/semver": "6.0.0",
"@types/yazl": "^2.4.1",
"@vercel/frameworks": "0.1.2-canary.1",
"@vercel/frameworks": "0.1.2-canary.2",
"@vercel/ncc": "0.24.0",
"aggregate-error": "3.0.1",
"async-retry": "1.2.3",

View File

@@ -24,6 +24,7 @@ interface Options {
projectSettings?: {
framework?: string | null;
devCommand?: string | null;
installCommand?: string | null;
buildCommand?: string | null;
outputDirectory?: string | null;
createdAt?: number;
@@ -450,6 +451,10 @@ function detectFrontBuilder(
config.devCommand = projectSettings.devCommand;
}
if (projectSettings.installCommand) {
config.installCommand = projectSettings.installCommand;
}
if (projectSettings.buildCommand) {
config.buildCommand = projectSettings.buildCommand;
}

View File

@@ -41,6 +41,7 @@ export interface Config {
import?: { [key: string]: string };
functions?: BuilderFunctions;
outputDirectory?: string;
installCommand?: string;
buildCommand?: string;
devCommand?: string;
framework?: string;

View File

@@ -1,6 +1,6 @@
{
"name": "vercel",
"version": "20.1.3-canary.5",
"version": "20.1.3-canary.7",
"preferGlobal": true,
"license": "Apache-2.0",
"description": "The command-line interface for Vercel",
@@ -61,7 +61,7 @@
"node": ">= 10"
},
"dependencies": {
"@vercel/build-utils": "2.5.5-canary.1",
"@vercel/build-utils": "2.5.5-canary.3",
"@vercel/go": "1.1.6",
"@vercel/node": "1.8.4",
"@vercel/python": "1.2.3",
@@ -100,7 +100,7 @@
"@types/universal-analytics": "0.4.2",
"@types/which": "1.3.2",
"@types/write-json-file": "2.2.1",
"@vercel/frameworks": "0.1.2-canary.1",
"@vercel/frameworks": "0.1.2-canary.2",
"@vercel/ncc": "0.24.0",
"@zeit/fun": "0.11.2",
"@zeit/source-map-support": "0.6.2",

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/client",
"version": "9.0.4-canary.1",
"version": "9.0.4-canary.4",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"homepage": "https://vercel.com",
@@ -37,7 +37,7 @@
]
},
"dependencies": {
"@vercel/build-utils": "2.5.5-canary.1",
"@vercel/build-utils": "2.5.5-canary.3",
"@zeit/fetch": "5.2.0",
"async-retry": "1.2.3",
"async-sema": "3.0.0",

View File

@@ -136,6 +136,7 @@ export async function getVercelIgnore(
'__pycache__',
'venv',
'CVS',
'.vercel_build_output',
];
const cwds = Array.isArray(cwd) ? cwd : [cwd];

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/next",
"version": "2.6.38",
"version": "2.6.39-canary.0",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",

View File

@@ -732,7 +732,7 @@ export const build = async ({
src: path.join(
'/',
entryDirectory,
'_next/static/(?:[^/]+/pages|pages|chunks|runtime|css|media)/.+'
`_next/static/(?:[^/]+/pages|pages|chunks|runtime|css|media|${escapedBuildId})/.+`
),
// Next.js assets contain a hash or entropy in their filenames, so they
// are guaranteed to be unique and cacheable indefinitely.
@@ -2296,7 +2296,7 @@ export const build = async ({
src: path.join(
'/',
entryDirectory,
'_next/static/(?:[^/]+/pages|pages|chunks|runtime|css|media)/.+'
`_next/static/(?:[^/]+/pages|pages|chunks|runtime|css|media|${escapedBuildId})/.+`
),
// Next.js assets contain a hash or entropy in their filenames, so they
// are guaranteed to be unique and cacheable indefinitely.

View File

@@ -8,6 +8,12 @@
"cache-control": "public,max-age=31536000,immutable"
}
},
{
"path": "/_next/static/testing-build-id/_buildManifest.js",
"responseHeaders": {
"cache-control": "public,max-age=31536000,immutable"
}
},
{
"path": "/_next/static/invalid-build-id/pages/non-existent.js",
"notResponseHeaders": {

View File

@@ -8,6 +8,12 @@
"cache-control": "public,max-age=31536000,immutable"
}
},
{
"path": "/_next/static/testing-build-id/_buildManifest.js",
"responseHeaders": {
"cache-control": "public,max-age=31536000,immutable"
}
},
{
"path": "/",
"mustContain": "nextExport\":true"

View File

@@ -3,3 +3,6 @@ dist/
# bypass all ignored files for the cache fixtures
# because they contain node_modules and package-lock.json files
!test/cache-fixtures/**
/src/bridge.ts
/src/launcher.ts

View File

@@ -1,8 +1,17 @@
#!/bin/bash
set -euo pipefail
# Copy shared dependencies
bridge_defs="$(dirname $(pwd))/now-node-bridge/src/bridge.ts"
launcher_defs="$(dirname $(pwd))/now-node/src/launcher.ts"
cp -v "$bridge_defs" src
cp -v "$launcher_defs" src
# Start fresh
rm -rf dist
tsc
# Build with `ncc`
ncc build src/index.ts -e @vercel/build-utils -e @now/build-utils -o dist

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/static-build",
"version": "0.17.11",
"version": "0.17.15",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/build-step",
@@ -19,6 +19,7 @@
"prepublishOnly": "./build.sh"
},
"devDependencies": {
"@types/aws-lambda": "8.10.64",
"@types/cross-spawn": "6.0.0",
"@types/ms": "0.7.31",
"@types/node-fetch": "2.5.4",

View File

@@ -33,6 +33,7 @@ const {
NowBuildError,
} = buildUtils;
import { Route, Source } from '@vercel/routing-utils';
import { readBuildOutputDirectory } from './utils/read-build-output';
import * as GatsbyUtils from './utils/gatsby';
const sleep = (n: number) => new Promise(resolve => setTimeout(resolve, n));
@@ -489,31 +490,48 @@ export async function build({
}
}
validateDistDir(distPath);
const extraOutputs = await readBuildOutputDirectory({ workPath });
if (framework) {
if (extraOutputs.staticFiles) {
output = Object.assign(
{},
extraOutputs.staticFiles,
extraOutputs.functions
);
} else {
// No need to verify the dist dir if there are other output files.
if (!extraOutputs.functions) {
validateDistDir(distPath);
}
let ignore: string[] = [];
if (config.zeroConfig && config.outputDirectory === '.') {
ignore = [
'.env',
'.env.*',
'.git/**',
'.vercel/**',
'node_modules/**',
'yarn.lock',
'package-lock.json',
'package.json',
'.vercel_build_output',
];
debug(`Using ignore: ${JSON.stringify(ignore)}`);
}
output = await glob('**', { cwd: distPath, ignore }, mountpoint);
Object.assign(output, extraOutputs.functions);
}
if (extraOutputs.routes) {
routes.push(...extraOutputs.routes);
} else if (framework) {
const frameworkRoutes = await getFrameworkRoutes(
framework,
outputDirPrefix
);
routes.push(...frameworkRoutes);
}
let ignore: string[] = [];
if (config.zeroConfig && config.outputDirectory === '.') {
ignore = [
'.env',
'.env.*',
'.git/**',
'.vercel/**',
'node_modules/**',
'yarn.lock',
'package-lock.json',
'package.json',
];
debug(`Using ignore: ${JSON.stringify(ignore)}`);
}
output = await glob('**', { cwd: distPath, ignore }, mountpoint);
}
const watch = [path.join(mountpoint.replace(/^\.\/?/, ''), '**/*')];

View File

@@ -1,6 +1,6 @@
import { PackageJson } from '@vercel/build-utils';
import { constants, PathLike, promises as fs } from 'fs';
import * as path from 'path';
import { PackageJson } from '@vercel/build-utils';
import path from 'path';
export type DeepWriteable<T> = {
-readonly [P in keyof T]: DeepWriteable<T[P]>;
@@ -38,3 +38,11 @@ export async function writePackageJson(
JSON.stringify(packageJson, null, 2)
);
}
export function isObjectEmpty(object: { [key: string]: unknown }) {
for (const _prop in object) {
return false;
}
return true;
}

View File

@@ -0,0 +1,157 @@
import { FileBlob, Files, Lambda } from '@vercel/build-utils';
import { isObjectEmpty } from './_shared';
import { makeNowLauncher } from '../launcher';
import { promises as fs } from 'fs';
import { Route } from '@vercel/routing-utils';
import buildUtils from '../build-utils';
import path from 'path';
const { createLambda, debug, getLatestNodeVersion, glob } = buildUtils;
/**
* Reads the .vercel_build_output directory and returns and object
* that should be merged with the build outputs.
*
* At the moment only `functions/node` is supported for functions.
*/
export async function readBuildOutputDirectory({
workPath,
}: {
workPath: string;
}) {
const functions: { [key: string]: Lambda } = {};
const functionsMountPath = path.join('.vercel', 'functions');
Object.assign(
functions,
await readNodeFunctions({ workPath, functionsMountPath })
);
const staticFiles = await readStaticFiles({ workPath });
const routes = await readRoutesConfig({ workPath });
const outputs = {
staticFiles: isObjectEmpty(staticFiles) ? null : staticFiles,
functions: isObjectEmpty(functions) ? null : functions,
routes: routes.length ? routes : null,
};
if (outputs.functions) {
console.log(
`Detected Serverless Functions in ".vercel_build_output/functions"`
);
}
if (outputs.staticFiles) {
console.log(`Detected Static Assets in ".vercel_build_output/static"`);
}
if (outputs.routes) {
console.log(`Detected Configuration in ".vercel_build_output/config"`);
}
return outputs;
}
async function readStaticFiles({
workPath,
}: {
workPath: string;
}): Promise<Files> {
const staticFilePath = path.join(workPath, '.vercel_build_output', 'static');
const staticFiles = await glob('**', {
cwd: staticFilePath,
});
return staticFiles;
}
async function readNodeFunctions({
workPath,
functionsMountPath,
}: {
workPath: string;
functionsMountPath: string;
}) {
const output: { [key: string]: Lambda } = {};
const nodeFunctionPath = path.join(
workPath,
'.vercel_build_output',
'functions',
'node'
);
const nodeFunctionFiles = await glob('*/index.js', {
cwd: nodeFunctionPath,
});
const nodeBridgeData = await fs.readFile(path.join(__dirname, 'bridge.js'));
for (const fileName of Object.keys(nodeFunctionFiles)) {
const launcherFileName = '___now_launcher';
const bridgeFileName = '___now_bridge';
const launcherFiles: Files = {
[`${launcherFileName}.js`]: new FileBlob({
data: makeNowLauncher({
entrypointPath: `./index.js`,
bridgePath: `./${bridgeFileName}`,
helpersPath: '',
sourcemapSupportPath: '',
shouldAddHelpers: false,
shouldAddSourcemapSupport: false,
}),
}),
[`${bridgeFileName}.js`]: new FileBlob({
data: nodeBridgeData,
}),
};
const requiredFiles = await glob('**', {
cwd: path.join(nodeFunctionPath, path.dirname(fileName)),
});
const lambda = await createLambda({
files: {
...requiredFiles,
...launcherFiles,
},
handler: `${launcherFileName}.launcher`,
runtime: getLatestNodeVersion().runtime,
});
const parsed = path.parse(fileName);
const newPath = path.join(functionsMountPath, parsed.dir, parsed.name);
output[newPath] = lambda;
debug(
`Created Lambda "${newPath}" from "${path.join(
nodeFunctionPath,
fileName
)}".`
);
}
return output;
}
async function readRoutesConfig({
workPath,
}: {
workPath: string;
}): Promise<Route[]> {
const routesConfigPath = path.join(
workPath,
'.vercel_build_output',
'config',
'routes.json'
);
try {
return JSON.parse(await fs.readFile(routesConfigPath, 'utf8')) || [];
} catch (error) {
if (error.code === 'ENOENT') {
return [];
}
throw error;
}
}

View File

@@ -0,0 +1 @@
.vercel_build_output

View File

@@ -0,0 +1,10 @@
[
{
"src": "/",
"dest": "/.vercel/functions/root/"
},
{
"src": "/(.*)",
"dest": "/.vercel/functions/$1"
}
]

View File

@@ -0,0 +1,5 @@
const { getAbout } = require('./util');
module.exports = async function (req, res) {
return res.end(`Hello from /about/index.js on ${req.url} - ${getAbout()}`);
};

View File

@@ -0,0 +1,5 @@
module.exports = {
getAbout() {
return 'Milkshake';
},
};

View File

@@ -0,0 +1,7 @@
const { getInfo } = require('./info');
module.exports = async function (req, res) {
return res.end(
`Hello from /product/index.js on ${req.url} - ${await getInfo()}`
);
};

View File

@@ -0,0 +1,5 @@
module.exports = {
async getInfo() {
return 'Information about a Product.';
},
};

View File

@@ -0,0 +1,3 @@
module.exports = async function (req, res) {
return res.end(`Hello from /root/index.js on ${req.url}`);
};

View File

@@ -0,0 +1,37 @@
{
"version": 2,
"builds": [
{
"src": "package.json",
"use": "@vercel/static-build",
"config": { "zeroConfig": true }
}
],
"probes": [
{
"path": "/.vercel/functions/root",
"mustContain": "Hello from /root/index.js on /.vercel/functions/root"
},
{ "path": "/", "mustContain": "Hello from /root/index.js on /" },
{
"path": "/.vercel/functions/about",
"mustContain": "Hello from /about/index.js on /.vercel/functions/about - Milkshake"
},
{
"path": "/about",
"mustContain": "Hello from /about/index.js on /about - Milkshake"
},
{ "path": "/.vercel/functions/about/util", "status": 404 },
{ "path": "/about/util", "status": 404 },
{
"path": "/.vercel/functions/product",
"mustContain": "Hello from /product/index.js on /.vercel/functions/product - Information about a Product"
},
{
"path": "/product",
"mustContain": "Hello from /product/index.js on /product - Information about a Product"
},
{ "path": "/.vercel/functions/product/info", "status": 404 },
{ "path": "/product/info", "status": 404 }
]
}

View File

@@ -0,0 +1,5 @@
{
"scripts": {
"build": "cp -r fake .vercel_build_output"
}
}

View File

@@ -0,0 +1 @@
.vercel_build_output

View File

@@ -0,0 +1,10 @@
[
{
"src": "/",
"dest": "/.vercel/functions/root/"
},
{
"src": "/(.*)",
"dest": "/.vercel/functions/$1"
}
]

View File

@@ -0,0 +1,5 @@
const { getAbout } = require('./util');
module.exports = async function (req, res) {
return res.end(`Hello from /about/index.js on ${req.url} - ${getAbout()}`);
};

View File

@@ -0,0 +1,5 @@
module.exports = {
getAbout() {
return 'Milkshake';
},
};

View File

@@ -0,0 +1,7 @@
const { getInfo } = require('./info');
module.exports = async function (req, res) {
return res.end(
`Hello from /product/index.js on ${req.url} - ${await getInfo()}`
);
};

View File

@@ -0,0 +1,5 @@
module.exports = {
async getInfo() {
return 'Information about a Product.';
},
};

View File

@@ -0,0 +1,3 @@
module.exports = async function (req, res) {
return res.end(`Hello from /root/index.js on ${req.url}`);
};

View File

@@ -0,0 +1,22 @@
{
"version": 2,
"builds": [
{
"src": "package.json",
"use": "@vercel/static-build",
"config": { "zeroConfig": true }
}
],
"probes": [
{ "path": "/static.txt", "mustContain": "static" },
{ "path": "/", "mustContain": "Hello from /root/index.js on /" },
{
"path": "/about",
"mustContain": "Hello from /about/index.js on /about - Milkshake"
},
{
"path": "/product",
"mustContain": "Hello from /product/index.js on /product - Information about a Product"
}
]
}

View File

@@ -0,0 +1,5 @@
{
"scripts": {
"build": "mkdir -p public && echo static > public/static.txt && cp -r fake .vercel_build_output"
}
}

View File

@@ -0,0 +1 @@
.vercel_build_output

View File

@@ -0,0 +1,10 @@
[
{
"src": "/",
"dest": "/.vercel/functions/root/"
},
{
"src": "/(.*)",
"dest": "/.vercel/functions/$1"
}
]

View File

@@ -0,0 +1,11 @@
{
"version": 2,
"builds": [
{
"src": "package.json",
"use": "@vercel/static-build",
"config": { "zeroConfig": true }
}
],
"probes": [{ "path": "/", "mustContain": "overwritten" }]
}

View File

@@ -0,0 +1,5 @@
{
"scripts": {
"build": "mkdir -p public && echo static > public/index.txt && cp -r fake .vercel_build_output"
}
}

View File

@@ -15,7 +15,6 @@
"strict": true,
"target": "esnext"
},
"exclude": [
"test/fixtures"
]
"include": ["src/**/*"],
"exclude": ["test/fixtures"]
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/redwood",
"version": "0.1.2-canary.1",
"version": "0.1.2-canary.2",
"main": "./dist/index.js",
"license": "MIT",
"homepage": "https://vercel.com/docs",
@@ -19,7 +19,7 @@
},
"dependencies": {
"@netlify/zip-it-and-ship-it": "1.2.0",
"@vercel/frameworks": "0.1.2-canary.1"
"@vercel/frameworks": "0.1.2-canary.2"
},
"devDependencies": {
"@types/aws-lambda": "8.10.19",

View File

@@ -1607,6 +1607,11 @@
resolved "https://registry.yarnpkg.com/@types/aws-lambda/-/aws-lambda-8.10.19.tgz#913a8016a4599d262960d97cb11faf7e963ec0e1"
integrity sha512-dEhQow/1awGGIf/unEpb97vsTtnQ3qRPAhSmZZcXKzs4nOVbIuWo5LCCzOYdSIkGkkoFXVvc8pBaSVKRYIFUBA==
"@types/aws-lambda@8.10.64":
version "8.10.64"
resolved "https://registry.yarnpkg.com/@types/aws-lambda/-/aws-lambda-8.10.64.tgz#4bdcb725aef96bef0cb1decf19c7efff1df22fe7"
integrity sha512-LRKk2UQCSi7BsO5TlfSI8cTNpOGz+MH6+RXEWtuZmxJficQgxwEYJDiKVirzgyiHce0L0F4CqCVvKTwblAeOUw==
"@types/babel__core@^7.1.0":
version "7.1.8"
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.8.tgz#057f725aca3641f49fc11c7a87a9de5ec588a5d7"