From 348115036ca01590b7f5f109eed9eca6e5a78843 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Tue, 6 Apr 2021 12:12:23 -0500 Subject: [PATCH 1/2] Ensure no-op export returns without error (#23752) This ensures we don't reach the invariant from trying to create the export progress with no items during `next build` or `next export` by returning immediately when we notice there are no paths being exported. Additional tests have been added to ensure these cases don't error. ## Bug - [x] Related issues linked using `fixes #number` - [x] Integration tests added Fixes: https://github.com/vercel/next.js/issues/23724 --- packages/next/export/index.ts | 4 + .../no-op-export/test/index.test.js | 103 ++++++++++++++++++ test/lib/next-test-utils.js | 8 ++ 3 files changed, 115 insertions(+) create mode 100644 test/integration/no-op-export/test/index.test.js diff --git a/packages/next/export/index.ts b/packages/next/export/index.ts index 5cdb87751fca2..59e4ff23de9f5 100644 --- a/packages/next/export/index.ts +++ b/packages/next/export/index.ts @@ -425,6 +425,10 @@ export default async function exportApp( hasApiRoutes = true } + if (filteredPaths.length === 0) { + return + } + if (prerenderManifest && !options.buildExport) { const fallbackEnabledPages = new Set() diff --git a/test/integration/no-op-export/test/index.test.js b/test/integration/no-op-export/test/index.test.js new file mode 100644 index 0000000000000..2710c02514964 --- /dev/null +++ b/test/integration/no-op-export/test/index.test.js @@ -0,0 +1,103 @@ +/* eslint-env jest */ + +import path from 'path' +import fs from 'fs-extra' +import { join } from 'path' +import { nextBuild, nextExport } from 'next-test-utils' + +jest.setTimeout(1000 * 60 * 2) + +const appDir = join(__dirname, '../') +const nextConfig = join(appDir, 'next.config.js') + +const addPage = async (page, content) => { + const pagePath = join(appDir, 'pages', page) + await fs.ensureDir(path.dirname(pagePath)) + await fs.writeFile(pagePath, content) +} + +describe('no-op export', () => { + afterEach(async () => { + await Promise.all( + ['.next', 'pages', 'next.config.js', 'out'].map((file) => + fs.remove(join(appDir, file)) + ) + ) + }) + + it('should not error for all server-side pages build', async () => { + await addPage( + '_error.js', + ` + import React from 'react' + export default class Error extends React.Component { + static async getInitialProps() { + return { + props: { + statusCode: 'oops' + } + } + } + render() { + return 'error page' + } + } + ` + ) + await addPage( + '[slug].js', + ` + export const getStaticProps = () => { + return { + props: {} + } + } + export const getStaticPaths = () => { + return { + paths: [], + fallback: false + } + } + export default function Page() { + return 'page' + } + ` + ) + const result = await nextBuild(appDir, undefined, { + stderr: 'log', + stdout: 'log', + }) + expect(result.code).toBe(0) + }) + + it('should not error for empty exportPathMap', async () => { + await addPage( + 'index.js', + ` + export default function Index() { + return 'hello world' + } + ` + ) + await fs.writeFile( + nextConfig, + ` + module.exports = { + exportPathMap() { + return {} + } + } + ` + ) + const buildResult = await nextBuild(appDir, undefined, { + stderr: 'log', + stdout: 'log', + }) + expect(buildResult.code).toBe(0) + + const exportResult = await nextExport(appDir, { + outdir: join(appDir, 'out'), + }) + expect(exportResult.code).toBe(0) + }) +}) diff --git a/test/lib/next-test-utils.js b/test/lib/next-test-utils.js index 6b31e1eff1871..14da3a40744c5 100644 --- a/test/lib/next-test-utils.js +++ b/test/lib/next-test-utils.js @@ -121,6 +121,10 @@ export function runNextCommand(argv, options = {}) { if (options.stderr) { instance.stderr.on('data', function (chunk) { stderrOutput += chunk + + if (options.stderr === 'log') { + console.log(chunk.toString()) + } }) } @@ -128,6 +132,10 @@ export function runNextCommand(argv, options = {}) { if (options.stdout) { instance.stdout.on('data', function (chunk) { stdoutOutput += chunk + + if (options.stdout === 'log') { + console.log(chunk.toString()) + } }) } From 23ad3a718950557d2e42e6ccc0302f363064f5a5 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Tue, 6 Apr 2021 12:26:23 -0500 Subject: [PATCH 2/2] v10.1.4-canary.2 --- lerna.json | 2 +- packages/create-next-app/package.json | 2 +- packages/eslint-plugin-next/package.json | 2 +- packages/next-bundle-analyzer/package.json | 2 +- packages/next-codemod/package.json | 2 +- packages/next-env/package.json | 2 +- packages/next-mdx/package.json | 2 +- packages/next-plugin-google-analytics/package.json | 2 +- packages/next-plugin-sentry/package.json | 2 +- packages/next-plugin-storybook/package.json | 2 +- packages/next-polyfill-module/package.json | 2 +- packages/next-polyfill-nomodule/package.json | 2 +- packages/next/package.json | 12 ++++++------ packages/react-dev-overlay/package.json | 2 +- packages/react-refresh-utils/package.json | 2 +- 15 files changed, 20 insertions(+), 20 deletions(-) diff --git a/lerna.json b/lerna.json index 98744409630cf..31d5867624045 100644 --- a/lerna.json +++ b/lerna.json @@ -17,5 +17,5 @@ "registry": "https://registry.npmjs.org/" } }, - "version": "10.1.4-canary.1" + "version": "10.1.4-canary.2" } diff --git a/packages/create-next-app/package.json b/packages/create-next-app/package.json index d5a8acf592e09..4a5c0b6ce467b 100644 --- a/packages/create-next-app/package.json +++ b/packages/create-next-app/package.json @@ -1,6 +1,6 @@ { "name": "create-next-app", - "version": "10.1.4-canary.1", + "version": "10.1.4-canary.2", "keywords": [ "react", "next", diff --git a/packages/eslint-plugin-next/package.json b/packages/eslint-plugin-next/package.json index 2fb64a5e8f690..a97581e9ebb04 100644 --- a/packages/eslint-plugin-next/package.json +++ b/packages/eslint-plugin-next/package.json @@ -1,6 +1,6 @@ { "name": "@next/eslint-plugin-next", - "version": "10.1.4-canary.1", + "version": "10.1.4-canary.2", "description": "ESLint plugin for NextJS.", "main": "lib/index.js", "license": "MIT", diff --git a/packages/next-bundle-analyzer/package.json b/packages/next-bundle-analyzer/package.json index 5955705bedb35..43d1b54002eeb 100644 --- a/packages/next-bundle-analyzer/package.json +++ b/packages/next-bundle-analyzer/package.json @@ -1,6 +1,6 @@ { "name": "@next/bundle-analyzer", - "version": "10.1.4-canary.1", + "version": "10.1.4-canary.2", "main": "index.js", "license": "MIT", "repository": { diff --git a/packages/next-codemod/package.json b/packages/next-codemod/package.json index fad01bce4cbeb..048571eec17d0 100644 --- a/packages/next-codemod/package.json +++ b/packages/next-codemod/package.json @@ -1,6 +1,6 @@ { "name": "@next/codemod", - "version": "10.1.4-canary.1", + "version": "10.1.4-canary.2", "license": "MIT", "dependencies": { "chalk": "4.1.0", diff --git a/packages/next-env/package.json b/packages/next-env/package.json index 4ee3d3ab6a585..fc16a099c8ffb 100644 --- a/packages/next-env/package.json +++ b/packages/next-env/package.json @@ -1,6 +1,6 @@ { "name": "@next/env", - "version": "10.1.4-canary.1", + "version": "10.1.4-canary.2", "keywords": [ "react", "next", diff --git a/packages/next-mdx/package.json b/packages/next-mdx/package.json index b54b29d181756..c4245e3964133 100644 --- a/packages/next-mdx/package.json +++ b/packages/next-mdx/package.json @@ -1,6 +1,6 @@ { "name": "@next/mdx", - "version": "10.1.4-canary.1", + "version": "10.1.4-canary.2", "main": "index.js", "license": "MIT", "repository": { diff --git a/packages/next-plugin-google-analytics/package.json b/packages/next-plugin-google-analytics/package.json index 3a43b88601d26..0bafed4fbfabd 100644 --- a/packages/next-plugin-google-analytics/package.json +++ b/packages/next-plugin-google-analytics/package.json @@ -1,6 +1,6 @@ { "name": "@next/plugin-google-analytics", - "version": "10.1.4-canary.1", + "version": "10.1.4-canary.2", "repository": { "url": "vercel/next.js", "directory": "packages/next-plugin-google-analytics" diff --git a/packages/next-plugin-sentry/package.json b/packages/next-plugin-sentry/package.json index ac2ecc8f0adde..1f20d931a1b2d 100644 --- a/packages/next-plugin-sentry/package.json +++ b/packages/next-plugin-sentry/package.json @@ -1,6 +1,6 @@ { "name": "@next/plugin-sentry", - "version": "10.1.4-canary.1", + "version": "10.1.4-canary.2", "repository": { "url": "vercel/next.js", "directory": "packages/next-plugin-sentry" diff --git a/packages/next-plugin-storybook/package.json b/packages/next-plugin-storybook/package.json index 7321965bc0d3f..03b248dd5ad84 100644 --- a/packages/next-plugin-storybook/package.json +++ b/packages/next-plugin-storybook/package.json @@ -1,6 +1,6 @@ { "name": "@next/plugin-storybook", - "version": "10.1.4-canary.1", + "version": "10.1.4-canary.2", "repository": { "url": "vercel/next.js", "directory": "packages/next-plugin-storybook" diff --git a/packages/next-polyfill-module/package.json b/packages/next-polyfill-module/package.json index 51e8f091ab166..de7523751ced5 100644 --- a/packages/next-polyfill-module/package.json +++ b/packages/next-polyfill-module/package.json @@ -1,6 +1,6 @@ { "name": "@next/polyfill-module", - "version": "10.1.4-canary.1", + "version": "10.1.4-canary.2", "description": "A standard library polyfill for ES Modules supporting browsers (Edge 16+, Firefox 60+, Chrome 61+, Safari 10.1+)", "main": "dist/polyfill-module.js", "license": "MIT", diff --git a/packages/next-polyfill-nomodule/package.json b/packages/next-polyfill-nomodule/package.json index 5d0bc209cc529..1e9eef9144519 100644 --- a/packages/next-polyfill-nomodule/package.json +++ b/packages/next-polyfill-nomodule/package.json @@ -1,6 +1,6 @@ { "name": "@next/polyfill-nomodule", - "version": "10.1.4-canary.1", + "version": "10.1.4-canary.2", "description": "A polyfill for non-dead, nomodule browsers.", "main": "dist/polyfill-nomodule.js", "license": "MIT", diff --git a/packages/next/package.json b/packages/next/package.json index 282a46f16af95..6eafa35c3bbff 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "10.1.4-canary.1", + "version": "10.1.4-canary.2", "description": "The React Framework", "main": "./dist/server/next.js", "license": "MIT", @@ -62,10 +62,10 @@ "dependencies": { "@babel/runtime": "7.12.5", "@hapi/accept": "5.0.1", - "@next/env": "10.1.4-canary.1", - "@next/polyfill-module": "10.1.4-canary.1", - "@next/react-dev-overlay": "10.1.4-canary.1", - "@next/react-refresh-utils": "10.1.4-canary.1", + "@next/env": "10.1.4-canary.2", + "@next/polyfill-module": "10.1.4-canary.2", + "@next/react-dev-overlay": "10.1.4-canary.2", + "@next/react-refresh-utils": "10.1.4-canary.2", "@opentelemetry/api": "0.14.0", "assert": "2.0.0", "ast-types": "0.13.2", @@ -146,7 +146,7 @@ "@babel/preset-react": "7.12.10", "@babel/preset-typescript": "7.12.7", "@babel/types": "7.12.12", - "@next/polyfill-nomodule": "10.1.4-canary.1", + "@next/polyfill-nomodule": "10.1.4-canary.2", "@taskr/clear": "1.1.0", "@taskr/esnext": "1.1.0", "@taskr/watch": "1.1.0", diff --git a/packages/react-dev-overlay/package.json b/packages/react-dev-overlay/package.json index d5698f7abad91..0346e7894069f 100644 --- a/packages/react-dev-overlay/package.json +++ b/packages/react-dev-overlay/package.json @@ -1,6 +1,6 @@ { "name": "@next/react-dev-overlay", - "version": "10.1.4-canary.1", + "version": "10.1.4-canary.2", "description": "A development-only overlay for developing React applications.", "repository": { "url": "vercel/next.js", diff --git a/packages/react-refresh-utils/package.json b/packages/react-refresh-utils/package.json index 58bc952e80c9f..046988e2b7a97 100644 --- a/packages/react-refresh-utils/package.json +++ b/packages/react-refresh-utils/package.json @@ -1,6 +1,6 @@ { "name": "@next/react-refresh-utils", - "version": "10.1.4-canary.1", + "version": "10.1.4-canary.2", "description": "An experimental package providing utilities for React Refresh.", "repository": { "url": "vercel/next.js",