diff --git a/errors/api-routes-static-export.md b/errors/api-routes-static-export.md index c72f305c93a..d82365e0d32 100644 --- a/errors/api-routes-static-export.md +++ b/errors/api-routes-static-export.md @@ -2,11 +2,13 @@ #### Why This Warning Occurred -An `exportPathMap` path was matched to an API route. `next export` will not prerender API routes to HTML. +An `exportPathMap` path was matched to an API route. Statically exporting a Next.js application via `next export` disables API routes. + +This command is meant for static-only hosts, and is not necessary to make your application static. Pages in your application without server-side data dependencies will be automatically statically exported by `next build`, including pages powered by `getStaticProps` #### Possible Ways to Fix It -Remove any paths using API routes from your `exportPathMap` in `next.config.js`. +Use `next build` with platforms that don't require `next export` like https://zeit.co or remove any paths using API routes from your `exportPathMap` in `next.config.js`. ### Useful Links diff --git a/packages/next/export/index.ts b/packages/next/export/index.ts index 5319e806755..bd930d44fa2 100644 --- a/packages/next/export/index.ts +++ b/packages/next/export/index.ts @@ -149,17 +149,19 @@ export default async function( const pages = options.pages || Object.keys(pagesManifest) const defaultPathMap: ExportPathMap = {} + let hasApiRoutes = false for (const page of pages) { // _document and _app are not real pages // _error is exported as 404.html later on // API Routes are Node.js functions - if ( - page === '/_document' || - page === '/_app' || - page === '/_error' || - page.match(API_ROUTE) - ) { + + if (page.match(API_ROUTE)) { + hasApiRoutes = true + continue + } + + if (page === '/_document' || page === '/_app' || page === '/_error') { continue } @@ -267,14 +269,30 @@ export default async function( // Remove API routes route => !exportPathMap[route].page.match(API_ROUTE) ) - const hasApiRoutes = exportPaths.length !== filteredPaths.length + + if (filteredPaths.length !== exportPaths.length) { + hasApiRoutes = true + } // Warn if the user defines a path for an API page if (hasApiRoutes) { log( - chalk.yellow( - ' API pages are not supported by next export. https://err.sh/zeit/next.js/api-routes-static-export' - ) + chalk.bold.red(`Attention`) + + ': ' + + chalk.yellow( + `Statically exporting a Next.js application via \`next export\` disables API routes.` + ) + + `\n` + + chalk.yellow( + `This command is meant for static-only hosts, and is` + + ' ' + + chalk.bold(`not necessary to make your application static.`) + ) + + `\n` + + chalk.yellow( + `Pages in your application without server-side data dependencies will be automatically statically exported by \`next build\`, including pages powered by \`getStaticProps\`.` + ) + + `\nLearn more: https://err.sh/zeit/next.js/api-routes-static-export` ) } diff --git a/test/integration/api-support/test/index.test.js b/test/integration/api-support/test/index.test.js index 669728eee61..c547d03b833 100644 --- a/test/integration/api-support/test/index.test.js +++ b/test/integration/api-support/test/index.test.js @@ -11,6 +11,7 @@ import { renderViaHTTP, nextBuild, nextStart, + nextExport, } from 'next-test-utils' import json from '../big.json' @@ -377,6 +378,17 @@ function runTests(dev = false) { ) }) } else { + it('should show warning with next export', async () => { + const { stdout } = await nextExport( + appDir, + { outdir: join(appDir, 'out') }, + { stdout: true } + ) + expect(stdout).toContain( + 'https://err.sh/zeit/next.js/api-routes-static-export' + ) + }) + it('should build api routes', async () => { const pagesManifest = JSON.parse( await fs.readFile( diff --git a/yarn.lock b/yarn.lock index 9b797f63899..88ef538a57b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4150,7 +4150,7 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@4.8.3, browserslist@^4.0.0, browserslist@^4.3.6, browserslist@^4.6.0, browserslist@^4.6.4, browserslist@^4.8.0, browserslist@^4.8.2, browserslist@^4.8.3: +browserslist@4.8.3, browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6, browserslist@^4.0.0, browserslist@^4.3.6, browserslist@^4.6.0, browserslist@^4.6.4, browserslist@^4.8.0, browserslist@^4.8.2, browserslist@^4.8.3: version "4.8.3" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.3.tgz#65802fcd77177c878e015f0e3189f2c4f627ba44" integrity sha512-iU43cMMknxG1ClEZ2MDKeonKE1CCrFVkQK2AqO2YWFmvIrx4JWrvQ4w4hQez6EpVI8rHTtqh/ruHHDHSOKxvUg== @@ -4159,14 +4159,6 @@ browserslist@4.8.3, browserslist@^4.0.0, browserslist@^4.3.6, browserslist@^4.6. electron-to-chromium "^1.3.322" node-releases "^1.1.44" -browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6: - version "1.7.7" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.7.7.tgz#0bd76704258be829b2398bb50e4b62d1a166b0b9" - integrity sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk= - dependencies: - caniuse-db "^1.0.30000639" - electron-to-chromium "^1.2.7" - browserstack-local@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/browserstack-local/-/browserstack-local-1.4.0.tgz#d979cac056f57b9af159b3bcd7fdc09b4354537c" @@ -4470,21 +4462,11 @@ caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634: resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30001023.tgz#f856f71af16a5a44e81f1fcefc1673912a43da72" integrity sha512-EnlshvE6oAum+wWwKmJNVaoqJMjIc0bLUy4Dj77VVnz1o6bzSPr1Ze9iPy6g5ycg1xD6jGU6vBmo7pLEz2MbCQ== -caniuse-db@^1.0.30000639: - version "1.0.30001036" - resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30001036.tgz#8761fb6cd423ef2d3f8d96a21d898932252dc477" - integrity sha512-plRkihXQyiDaFUXC7x/jAIXXTKiiaWvfAagsruh/vmstnRQ+a2a95HyENxiTr5WrkPSvmFUIvsRUalVFyeh2/w== - -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001012, caniuse-lite@^1.0.30001017, caniuse-lite@^1.0.30001019: +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001012, caniuse-lite@^1.0.30001017, caniuse-lite@^1.0.30001019, caniuse-lite@^1.0.30001020: version "1.0.30001019" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001019.tgz#857e3fccaad2b2feb3f1f6d8a8f62d747ea648e1" integrity sha512-6ljkLtF1KM5fQ+5ZN0wuyVvvebJxgJPTmScOMaFuQN2QuOzvRJnWSKfzQskQU5IOU4Gap3zasYPIinzwUjoj/g== -caniuse-lite@^1.0.30001020: - version "1.0.30001036" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001036.tgz#930ea5272010d8bf190d859159d757c0b398caf0" - integrity sha512-jU8CIFIj2oR7r4W+5AKcsvWNVIb6Q6OZE3UsrXrZBHFtreT4YgTeOJtTucp+zSedEpTi3L5wASSP0LYIE3if6w== - capitalize@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/capitalize/-/capitalize-1.0.0.tgz#dc802c580aee101929020d2ca14b4ca8a0ae44be" @@ -6276,11 +6258,6 @@ ejs@^2.6.1: resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== -electron-to-chromium@^1.2.7: - version "1.3.382" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.382.tgz#cad02da655c33f7a3d6ca7525bd35c17e90f3a8f" - integrity sha512-gJfxOcgnBlXhfnUUObsq3n3ReU8CT6S8je97HndYRkKsNZMJJ38zO/pI5aqO7L3Myfq+E3pqPyKK/ynyLEQfBA== - electron-to-chromium@^1.3.322: version "1.3.327" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.327.tgz#516f28b4271727004362b4ac814494ae64d9dde7"