mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-06 04:22:01 +00:00
[next][node][static-build] Execute "vercel-build" script if defined (#4863)
* [build-utils] Make `runPackageJsonScript()` run the `vercel-` or `now-` if defined in `package.json` * [build-utils] Export `getScriptName()` * [next] Use `getScriptName()` and `remove()` * [node] Update for `vercel-` * [static-build] Update for `vercel-` * Remove debug * Add `getScriptName()` unit tests * Test for `vercel-build` in e2e * Make platform name behavior be opt-in So that it's not a breaking behavior change. * Check for only "vercel-build" or "now-build", but not "build" * Simplify `getScriptName()` to return the first existing script in a possible set * Revert change * Fix test Co-authored-by: Joe Haddad <joe.haddad@zeit.co> Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
This commit is contained in:
@@ -7,6 +7,7 @@ const {
|
||||
getLambdaOptionsFromFunction,
|
||||
getNodeVersion,
|
||||
getSpawnOptions,
|
||||
getScriptName,
|
||||
glob,
|
||||
runNpmInstall,
|
||||
runPackageJsonScript,
|
||||
@@ -35,13 +36,7 @@ import {
|
||||
import { nodeFileTrace, NodeFileTraceReasons } from '@zeit/node-file-trace';
|
||||
import { ChildProcess, fork } from 'child_process';
|
||||
import escapeStringRegexp from 'escape-string-regexp';
|
||||
import {
|
||||
lstat,
|
||||
pathExists,
|
||||
readFile,
|
||||
unlink as unlinkFile,
|
||||
writeFile,
|
||||
} from 'fs-extra';
|
||||
import { lstat, pathExists, readFile, remove, writeFile } from 'fs-extra';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
import resolveFrom from 'resolve-from';
|
||||
@@ -108,13 +103,7 @@ const MAX_AGE_ONE_YEAR = 31536000;
|
||||
/**
|
||||
* Read package.json from files
|
||||
*/
|
||||
async function readPackageJson(
|
||||
entryPath: string
|
||||
): Promise<{
|
||||
scripts?: { [key: string]: string };
|
||||
dependencies?: { [key: string]: string };
|
||||
devDependencies?: { [key: string]: string };
|
||||
}> {
|
||||
async function readPackageJson(entryPath: string): Promise<PackageJson> {
|
||||
const packagePath = path.join(entryPath, 'package.json');
|
||||
|
||||
try {
|
||||
@@ -329,49 +318,38 @@ export const build = async ({
|
||||
}
|
||||
|
||||
const isLegacy = nextVersionRange && isLegacyNext(nextVersionRange);
|
||||
let shouldRunScript = 'now-build';
|
||||
|
||||
debug(`MODE: ${isLegacy ? 'legacy' : 'serverless'}`);
|
||||
|
||||
if (isLegacy) {
|
||||
try {
|
||||
await unlinkFile(path.join(entryPath, 'yarn.lock'));
|
||||
} catch (err) {
|
||||
debug('no yarn.lock removed');
|
||||
}
|
||||
|
||||
try {
|
||||
await unlinkFile(path.join(entryPath, 'package-lock.json'));
|
||||
} catch (err) {
|
||||
debug('no package-lock.json removed');
|
||||
}
|
||||
|
||||
console.warn(
|
||||
"WARNING: your application is being deployed in @vercel/next's legacy mode. http://err.sh/vercel/vercel/now-next-legacy-mode"
|
||||
);
|
||||
|
||||
await Promise.all([
|
||||
remove(path.join(entryPath, 'yarn.lock')),
|
||||
remove(path.join(entryPath, 'package-lock.json')),
|
||||
]);
|
||||
|
||||
debug('Normalizing package.json');
|
||||
const packageJson = normalizePackageJson(pkg);
|
||||
debug('Normalized package.json result: ', packageJson);
|
||||
await writePackageJson(entryPath, packageJson);
|
||||
} else if (pkg.scripts && pkg.scripts['now-build']) {
|
||||
debug('Found user `now-build` script');
|
||||
shouldRunScript = 'now-build';
|
||||
} else if (pkg.scripts && pkg.scripts['build']) {
|
||||
debug('Found user `build` script');
|
||||
shouldRunScript = 'build';
|
||||
} else if (!pkg.scripts || !pkg.scripts['now-build']) {
|
||||
debug(
|
||||
}
|
||||
|
||||
const buildScriptName = getScriptName(pkg, [
|
||||
'vercel-build',
|
||||
'now-build',
|
||||
'build',
|
||||
]);
|
||||
let { buildCommand } = config;
|
||||
|
||||
if (!buildScriptName && !buildCommand) {
|
||||
console.log(
|
||||
'Your application is being built using `next build`. ' +
|
||||
'If you need to define a different build step, please create a `now-build` script in your `package.json` ' +
|
||||
'(e.g. `{ "scripts": { "now-build": "npm run prepare && next build" } }`).'
|
||||
'If you need to define a different build step, please create a `vercel-build` script in your `package.json` ' +
|
||||
'(e.g. `{ "scripts": { "vercel-build": "npm run prepare && next build" } }`).'
|
||||
);
|
||||
pkg.scripts = {
|
||||
'now-build': 'next build',
|
||||
...(pkg.scripts || {}),
|
||||
};
|
||||
shouldRunScript = 'now-build';
|
||||
await writePackageJson(entryPath, pkg);
|
||||
buildCommand = 'next build';
|
||||
}
|
||||
|
||||
if (process.env.NPM_AUTH_TOKEN) {
|
||||
@@ -398,12 +376,11 @@ export const build = async ({
|
||||
await createServerlessConfig(workPath, entryPath, nextVersion);
|
||||
}
|
||||
|
||||
debug('Running user script...');
|
||||
const memoryToConsume = Math.floor(os.totalmem() / 1024 ** 2) - 128;
|
||||
const env: { [key: string]: string | undefined } = { ...spawnOpts.env };
|
||||
env.NODE_OPTIONS = `--max_old_space_size=${memoryToConsume}`;
|
||||
|
||||
if (config.buildCommand) {
|
||||
if (buildCommand) {
|
||||
// Add `node_modules/.bin` to PATH
|
||||
const nodeBinPath = await getNodeBinPath({ cwd: entryPath });
|
||||
env.PATH = `${nodeBinPath}${path.delimiter}${env.PATH}`;
|
||||
@@ -412,14 +389,14 @@ export const build = async ({
|
||||
`Added "${nodeBinPath}" to PATH env because a build command was used.`
|
||||
);
|
||||
|
||||
console.log(`Running "${config.buildCommand}"`);
|
||||
await execCommand(config.buildCommand, {
|
||||
console.log(`Running "${buildCommand}"`);
|
||||
await execCommand(buildCommand, {
|
||||
...spawnOpts,
|
||||
cwd: entryPath,
|
||||
env,
|
||||
});
|
||||
} else {
|
||||
await runPackageJsonScript(entryPath, shouldRunScript, {
|
||||
} else if (buildScriptName) {
|
||||
await runPackageJsonScript(entryPath, buildScriptName, {
|
||||
...spawnOpts,
|
||||
env,
|
||||
});
|
||||
@@ -667,7 +644,7 @@ export const build = async ({
|
||||
}
|
||||
|
||||
if (process.env.NPM_AUTH_TOKEN) {
|
||||
await unlinkFile(path.join(entryPath, '.npmrc'));
|
||||
await remove(path.join(entryPath, '.npmrc'));
|
||||
}
|
||||
|
||||
const pageLambdaRoutes: Route[] = [];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"scripts": {
|
||||
"build": "next build && next export"
|
||||
"now-build": "next build && next export"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"scripts": {
|
||||
"build": "next build && next export"
|
||||
"vercel-build": "next build && next export"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
|
||||
@@ -361,10 +361,12 @@ export async function build({
|
||||
meta,
|
||||
});
|
||||
|
||||
debug('Running user script...');
|
||||
const runScriptTime = Date.now();
|
||||
await runPackageJsonScript(entrypointFsDirname, 'now-build', spawnOpts);
|
||||
debug(`Script complete [${Date.now() - runScriptTime}ms]`);
|
||||
await runPackageJsonScript(
|
||||
entrypointFsDirname,
|
||||
// Don't consider "build" script since its intended for frontend code
|
||||
['vercel-build', 'now-build'],
|
||||
spawnOpts
|
||||
);
|
||||
|
||||
debug('Tracing input files...');
|
||||
const traceTime = Date.now();
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# Start fresh
|
||||
rm -rf dist
|
||||
|
||||
# Build with `ncc`
|
||||
ncc build src/index.ts -e @vercel/build-utils -e @now/build-utils -o dist
|
||||
|
||||
@@ -264,7 +264,6 @@ export async function build({
|
||||
const pkg = getPkg(entrypoint, workPath);
|
||||
|
||||
const devScript = pkg ? getScriptName(pkg, 'dev', config) : null;
|
||||
const buildScript = pkg ? getScriptName(pkg, 'build', config) : null;
|
||||
|
||||
const framework = getFramework(config, pkg);
|
||||
|
||||
@@ -431,8 +430,6 @@ export async function build({
|
||||
|
||||
if (buildCommand) {
|
||||
debug(`Executing "${buildCommand}"`);
|
||||
} else {
|
||||
debug(`Running "${buildScript}" in "${entrypoint}"`);
|
||||
}
|
||||
|
||||
const found =
|
||||
@@ -441,12 +438,16 @@ export async function build({
|
||||
...spawnOpts,
|
||||
cwd: entrypointDir,
|
||||
})
|
||||
: await runPackageJsonScript(entrypointDir, buildScript!, spawnOpts);
|
||||
: await runPackageJsonScript(
|
||||
entrypointDir,
|
||||
['vercel-build', 'now-build', 'build'],
|
||||
spawnOpts
|
||||
);
|
||||
|
||||
if (!found) {
|
||||
throw new Error(
|
||||
`Missing required "${
|
||||
buildCommand || buildScript
|
||||
buildCommand || 'vercel-build'
|
||||
}" script in "${entrypoint}"`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"scripts": {
|
||||
"now-build": "mkdir dist && node build.js"
|
||||
"vercel-build": "mkdir dist && node build.js"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ const testsThatFailToBuild = new Map([
|
||||
['05-empty-dist-dir', 'The Output Directory "dist" is empty.'],
|
||||
[
|
||||
'06-missing-script',
|
||||
'Missing required "now-build" script in "package.json"',
|
||||
'Missing required "vercel-build" script in "package.json"',
|
||||
],
|
||||
['07-nonzero-sh', 'Command "./build.sh" exited with 1'],
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user