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
This commit is contained in:
Tim Neutkens 2020-12-08 16:16:56 +01:00 committed by GitHub
parent cf4665539a
commit c792317295
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 135 additions and 5 deletions

View file

@ -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.

View file

@ -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.

View file

@ -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)

View file

@ -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(

View file

@ -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`
)
}

View file

@ -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,
},
]
},
}

View file

@ -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/)
})
})

View file

@ -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,
},
]
},
}

View file

@ -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/)
})
})