From c792317295c076e0b449ada10571b0716e395111 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 8 Dec 2020 16:16:56 +0100 Subject: [PATCH] Clear up production build missing message for `next start` and `next export` (#19777) Adds an err.sh link to the production build missing message. Also clears up `valid` as `production`. Also fixes an edge case where an unhelpful error would be thrown because we checked for `.next` instead of `.next/BUILD_ID` Added the out directory location as the list line during export to make sure people know where the files are output. Fixes #19778 Fixes #19788 --- errors/next-export-no-build-id.md | 10 +++++ errors/production-start-no-build-id.md | 10 +++++ packages/next/cli/next-export.ts | 2 +- packages/next/export/index.ts | 8 ++-- .../next/next-server/server/next-server.ts | 2 +- .../export-no-build/next.config.js | 39 +++++++++++++++++++ .../export-no-build/test/index.test.js | 13 +++++++ .../production-start-no-build/next.config.js | 39 +++++++++++++++++++ .../test/index.test.js | 17 ++++++++ 9 files changed, 135 insertions(+), 5 deletions(-) create mode 100644 errors/next-export-no-build-id.md create mode 100644 errors/production-start-no-build-id.md create mode 100644 test/integration/export-no-build/next.config.js create mode 100644 test/integration/export-no-build/test/index.test.js create mode 100644 test/integration/production-start-no-build/next.config.js create mode 100644 test/integration/production-start-no-build/test/index.test.js diff --git a/errors/next-export-no-build-id.md b/errors/next-export-no-build-id.md new file mode 100644 index 0000000000..affed88c30 --- /dev/null +++ b/errors/next-export-no-build-id.md @@ -0,0 +1,10 @@ +# Could not find a production build + +#### Why This Error Occurred + +When running `next export` a production build is needed. + +#### Possible Ways to Fix It + +- Run `next build` to create a production build before running `next export`. +- If your intention was to run the development server run `next dev` instead. diff --git a/errors/production-start-no-build-id.md b/errors/production-start-no-build-id.md new file mode 100644 index 0000000000..c6c9bfdb93 --- /dev/null +++ b/errors/production-start-no-build-id.md @@ -0,0 +1,10 @@ +# Could not find a production build + +#### Why This Error Occurred + +When running `next start` or a custom server in production mode a production build is needed. + +#### Possible Ways to Fix It + +- Run `next build` to create a production build before booting up the production server. +- If your intention was to run the development server run `next dev` instead. diff --git a/packages/next/cli/next-export.ts b/packages/next/cli/next-export.ts index f13533bd26..272877f920 100755 --- a/packages/next/cli/next-export.ts +++ b/packages/next/cli/next-export.ts @@ -62,7 +62,7 @@ const nextExport: cliCommand = (argv) => { exportApp(dir, options) .then(() => { - printAndExit('Export successful', 0) + printAndExit(`Export successful. Files written to ${options.outdir}`, 0) }) .catch((err) => { printAndExit(err) diff --git a/packages/next/export/index.ts b/packages/next/export/index.ts index a0c5d26f7d..010651fdf5 100644 --- a/packages/next/export/index.ts +++ b/packages/next/export/index.ts @@ -164,9 +164,11 @@ export default async function exportApp( Log.info(`using build directory: ${distDir}`) } - if (!existsSync(distDir)) { + const buildIdFile = join(distDir, BUILD_ID_FILE) + + if (!existsSync(buildIdFile)) { throw new Error( - `Build directory ${distDir} does not exist. Make sure you run "next build" before running "next start" or "next export".` + `Could not find a production build in the '${distDir}' directory. Try building your app with 'next build' before starting the static export. https://err.sh/vercel/next.js/next-export-no-build-id` ) } @@ -186,7 +188,7 @@ export default async function exportApp( ) } - const buildId = readFileSync(join(distDir, BUILD_ID_FILE), 'utf8') + const buildId = readFileSync(buildIdFile, 'utf8') const pagesManifest = !options.pages && (require(join( diff --git a/packages/next/next-server/server/next-server.ts b/packages/next/next-server/server/next-server.ts index 622c615099..7a8d2e9aaf 100644 --- a/packages/next/next-server/server/next-server.ts +++ b/packages/next/next-server/server/next-server.ts @@ -1899,7 +1899,7 @@ export default class Server { } catch (err) { if (!fs.existsSync(buildIdFile)) { throw new Error( - `Could not find a valid build in the '${this.distDir}' directory! Try building your app with 'next build' before starting the server.` + `Could not find a production build in the '${this.distDir}' directory. Try building your app with 'next build' before starting the production server. https://err.sh/vercel/next.js/production-start-no-build-id` ) } diff --git a/test/integration/export-no-build/next.config.js b/test/integration/export-no-build/next.config.js new file mode 100644 index 0000000000..1f568747f8 --- /dev/null +++ b/test/integration/export-no-build/next.config.js @@ -0,0 +1,39 @@ +module.exports = { + onDemandEntries: { + // Make sure entries are not getting disposed. + maxInactiveAge: 1000 * 60 * 60, + }, + rewrites() { + // add a rewrite so the code isn't dead-code eliminated + return [ + { + source: '/some-rewrite', + destination: '/', + }, + ] + }, + redirects() { + return [ + { + source: '/redirect/me/to-about/:lang', + destination: '/:lang/about', + permanent: false, + }, + { + source: '/nonexistent', + destination: '/about', + permanent: false, + }, + { + source: '/shadowed-page', + destination: '/about', + permanent: false, + }, + { + source: '/redirect-query-test/:path', + destination: '/about?foo=:path', + permanent: false, + }, + ] + }, +} diff --git a/test/integration/export-no-build/test/index.test.js b/test/integration/export-no-build/test/index.test.js new file mode 100644 index 0000000000..bd3ca813b4 --- /dev/null +++ b/test/integration/export-no-build/test/index.test.js @@ -0,0 +1,13 @@ +/* eslint-env jest */ +import { nextExport } from 'next-test-utils' +import { join } from 'path' +const appDir = join(__dirname, '../') +jest.setTimeout(1000 * 60 * 5) + +describe('next export without build', () => { + it('should show error when there is no production build', async () => { + const result = await nextExport(appDir, {}, { stderr: true, stdout: true }) + console.log(result.stdout, result.stderr) + expect(result.stderr).toMatch(/Could not find a production build in the/) + }) +}) diff --git a/test/integration/production-start-no-build/next.config.js b/test/integration/production-start-no-build/next.config.js new file mode 100644 index 0000000000..1f568747f8 --- /dev/null +++ b/test/integration/production-start-no-build/next.config.js @@ -0,0 +1,39 @@ +module.exports = { + onDemandEntries: { + // Make sure entries are not getting disposed. + maxInactiveAge: 1000 * 60 * 60, + }, + rewrites() { + // add a rewrite so the code isn't dead-code eliminated + return [ + { + source: '/some-rewrite', + destination: '/', + }, + ] + }, + redirects() { + return [ + { + source: '/redirect/me/to-about/:lang', + destination: '/:lang/about', + permanent: false, + }, + { + source: '/nonexistent', + destination: '/about', + permanent: false, + }, + { + source: '/shadowed-page', + destination: '/about', + permanent: false, + }, + { + source: '/redirect-query-test/:path', + destination: '/about?foo=:path', + permanent: false, + }, + ] + }, +} diff --git a/test/integration/production-start-no-build/test/index.test.js b/test/integration/production-start-no-build/test/index.test.js new file mode 100644 index 0000000000..01e30da1f3 --- /dev/null +++ b/test/integration/production-start-no-build/test/index.test.js @@ -0,0 +1,17 @@ +/* eslint-env jest */ +import { nextServer } from 'next-test-utils' +import { join } from 'path' +const appDir = join(__dirname, '../') +jest.setTimeout(1000 * 60 * 5) + +describe('Production Usage without production build', () => { + it('should show error when there is no production build', async () => { + expect(() => { + nextServer({ + dir: appDir, + dev: false, + quiet: true, + }) + }).toThrow(/Could not find a production build in the/) + }) +}) -- GitLab