From c1a1583dd0f60fe4dfc67773951bba46bf143757 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 12 Oct 2023 10:07:02 +0200 Subject: [PATCH 01/25] Fix reconnection loop when devserver is offline (#56698) Ensures the webpack-hmr socket is not reconnected infinitely while (and very quickly) when the dev server is offline. I've implemented a gradual backoff, after 5 tries at 1 second it'll try 20 times at 5 seconds. After those 25 retries it reloads the page as something must be wrong (i.e. the server is offline). --- .../src/client/dev/error-overlay/websocket.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/next/src/client/dev/error-overlay/websocket.ts b/packages/next/src/client/dev/error-overlay/websocket.ts index 5a90b045d186c..b59cc8052d0e0 100644 --- a/packages/next/src/client/dev/error-overlay/websocket.ts +++ b/packages/next/src/client/dev/error-overlay/websocket.ts @@ -26,11 +26,14 @@ export function sendMessage(data: string) { return source.send(data) } +let reconnections = 0 + export function connectHMR(options: { path: string; assetPrefix: string }) { function init() { if (source) source.close() function handleOnline() { + reconnections = 0 window.console.log('[HMR] connected') } @@ -42,11 +45,21 @@ export function connectHMR(options: { path: string; assetPrefix: string }) { } } + let timer: ReturnType function handleDisconnect() { source.onerror = null source.onclose = null source.close() - init() + reconnections++ + // After 25 reconnects we'll want to reload the page as it indicates the dev server is no longer running. + if (reconnections > 25) { + window.location.reload() + return + } + + clearTimeout(timer) + // Try again after 5 seconds + timer = setTimeout(init, reconnections > 5 ? 5000 : 1000) } const { hostname, port } = location From 35a99232c0b0af6e2b54af62b9dc0a04440dd69e Mon Sep 17 00:00:00 2001 From: Jimmy Lai Date: Thu, 12 Oct 2023 10:27:44 +0200 Subject: [PATCH 02/25] misc: tweak stats github action (#56694) This PR adds a few tweaks to our Github actions PR: - expand by default the main section - add some heuristics to not show hash/id changes in the diff view - add some heuristics to not show increase/decrease size when it's too small (100 bytes is noise most often) - add rendering runtimes to the list of tracked files after vs before ![CleanShot 2023-10-11 at 14 56 36@2x](https://github.com/vercel/next.js/assets/11064311/548781bc-e893-45d1-aca4-de73b2b30299) ![CleanShot 2023-10-11 at 14 57 11@2x](https://github.com/vercel/next.js/assets/11064311/8e1c77e3-bed5-46ec-a756-62496df6729e) --- .../next-stats-action/src/add-comment.js | 39 +++++++++------ .../src/run/collect-diffs.js | 47 ++++++++++++++++++- test/.stats-app/stats-config.js | 4 ++ 3 files changed, 75 insertions(+), 15 deletions(-) diff --git a/.github/actions/next-stats-action/src/add-comment.js b/.github/actions/next-stats-action/src/add-comment.js index a873067034049..c65e54236e44d 100644 --- a/.github/actions/next-stats-action/src/add-comment.js +++ b/.github/actions/next-stats-action/src/add-comment.js @@ -24,6 +24,8 @@ const shortenLabel = (itemKey) => : itemKey const twoMB = 2 * 1024 * 1024 +const ONE_HUNDRED_BYTES = 100 +const ONE_HUNDRED_MS = 100 module.exports = async function addComment( results = [], @@ -82,24 +84,21 @@ module.exports = async function addComment( // otherwise only show gzip values else if (!isGzipItem && !groupKey.match(gzipIgnoreRegex)) return - if ( - !itemKey.startsWith('buildDuration') || - (isBenchmark && itemKey.match(/req\/sec/)) - ) { - if (typeof mainItemVal === 'number') mainRepoTotal += mainItemVal - if (typeof diffItemVal === 'number') diffRepoTotal += diffItemVal - } - // calculate the change if (mainItemVal !== diffItemVal) { if ( typeof mainItemVal === 'number' && typeof diffItemVal === 'number' ) { - change = round(diffItemVal - mainItemVal, 2) + const roundedValue = round(diffItemVal - mainItemVal, 2) // check if there is still a change after rounding - if (change !== 0) { + if ( + roundedValue !== 0 && + ((prettyType === 'ms' && roundedValue > ONE_HUNDRED_MS) || + (prettyType === 'bytes' && roundedValue > ONE_HUNDRED_BYTES)) + ) { + change = roundedValue const absChange = Math.abs(change) const warnIfNegative = isBenchmark && itemKey.match(/req\/sec/) const warn = warnIfNegative @@ -112,12 +111,22 @@ module.exports = async function addComment( change = `${warn}${change < 0 ? '-' : '+'}${ useRawValue ? absChange : prettify(absChange, prettyType) }` + } else { + change = 'N/A' } } else { change = 'N/A' } } + if ( + (change !== 'N/A' && !itemKey.startsWith('buildDuration')) || + (isBenchmark && itemKey.match(/req\/sec/)) + ) { + if (typeof mainItemVal === 'number') mainRepoTotal += mainItemVal + if (typeof diffItemVal === 'number') diffRepoTotal += diffItemVal + } + groupTable += `| ${ isBenchmark ? itemKey : shortenLabel(itemKey) } | ${mainItemStr} | ${diffItemStr} | ${change} |\n` @@ -169,8 +178,7 @@ module.exports = async function addComment( // add diffs if (result.diffs) { - const diffHeading = '#### Diffs\n' - let diffContent = diffHeading + let diffContent = '' Object.keys(result.diffs).forEach((itemKey) => { const curDiff = result.diffs[itemKey] @@ -187,8 +195,11 @@ module.exports = async function addComment( diffContent += `\n\n` }) - if (diffContent !== diffHeading) { + if (diffContent.length > 0) { + resultContent += `
\n` + resultContent += `Diff details\n\n` resultContent += diffContent + resultContent += `\n
\n\n` } } let increaseDecreaseNote = '' @@ -199,7 +210,7 @@ module.exports = async function addComment( increaseDecreaseNote = ' (Decrease detected ✓)' } - comment += `
\n` + comment += `
\n` comment += `${result.title}${increaseDecreaseNote}\n\n
\n\n` comment += resultContent comment += '
\n' diff --git a/.github/actions/next-stats-action/src/run/collect-diffs.js b/.github/actions/next-stats-action/src/run/collect-diffs.js index 80dd9a26ce24b..c850fb843ab9e 100644 --- a/.github/actions/next-stats-action/src/run/collect-diffs.js +++ b/.github/actions/next-stats-action/src/run/collect-diffs.js @@ -106,7 +106,7 @@ module.exports = async function collectDiffs( `cd ${diffingDir} && git diff --minimal HEAD ${file}` ) stdout = (stdout.split(file).pop() || '').trim() - if (stdout.length > 0) { + if (stdout.length > 0 && !isLikelyHashOrIDChange(stdout)) { diffs[fileKey] = stdout } } catch (err) { @@ -117,3 +117,48 @@ module.exports = async function collectDiffs( } return diffs } + +function isLikelyHashOrIDChange(diff) { + const lines = diff.split('\n') + let additions = [] + let deletions = [] + + // Separate additions and deletions + for (const line of lines) { + if (line.startsWith('+')) { + additions.push(line.substring(1).split(/\b/)) + } else if (line.startsWith('-')) { + deletions.push(line.substring(1).split(/\b/)) + } + } + + // If the number of additions and deletions is different, it's not a hash or ID change + if (additions.length !== deletions.length) { + return false + } + + // Compare each addition with each deletion + for (let i = 0; i < additions.length; i++) { + const additionTokens = additions[i] + const deletionTokens = deletions[i] + + // Identify differing tokens + const differingTokens = additionTokens.filter( + (token, index) => token !== deletionTokens[index] + ) + + // Analyze differing tokens + for (const token of differingTokens) { + const isLikelyHash = /^[a-f0-9]+$/.test(token) + const isLikelyID = /^[0-9]+$/.test(token) + // this is most likely noise because some path include the repo name, which can be main or diff + const isLikelyNoise = ['main', 'diff'].includes(token) + + if (!isLikelyHash && !isLikelyID && !isLikelyNoise) { + return false + } + } + } + + return true +} diff --git a/test/.stats-app/stats-config.js b/test/.stats-app/stats-config.js index e28680d4259c7..f10676a4fcf06 100644 --- a/test/.stats-app/stats-config.js +++ b/test/.stats-app/stats-config.js @@ -36,6 +36,10 @@ const clientGlobs = [ '.next/server/edge-runtime-webpack.js', ], }, + { + name: 'Next Runtimes', + globs: ['../../node_modules/next/dist/compiled/next-server/**/*.js'], + }, ] const renames = [ From f2ce230728034077e34a130070c781b7655ca0c1 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 12 Oct 2023 10:38:31 +0200 Subject: [PATCH 03/25] Fix ensurePage for client-side navigation to / in Turbopack (#56704) While investigating the failing test case of `test/integration/scroll-forward-restoration/test/index.test.js` I found that navigating from `/another` to `/` using `next/link` with a `href="/"` errored on `ensurePage` as "this page was not built". Turns normalization wasn't applied on these so the input `page` was `/index` instead of `/`, where it expects `/` as the input. --- .../next/src/server/lib/router-utils/setup-dev-bundler.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/next/src/server/lib/router-utils/setup-dev-bundler.ts b/packages/next/src/server/lib/router-utils/setup-dev-bundler.ts index 0aace1745121b..17562efdcac23 100644 --- a/packages/next/src/server/lib/router-utils/setup-dev-bundler.ts +++ b/packages/next/src/server/lib/router-utils/setup-dev-bundler.ts @@ -116,6 +116,7 @@ import { import { normalizeMetadataRoute } from '../../../lib/metadata/get-metadata-route' import { clearModuleContext } from '../render-server' import type { ActionManifest } from '../../../build/webpack/plugins/flight-client-entry-plugin' +import { denormalizePagePath } from '../../../shared/lib/page-path/denormalize-page-path' const wsServer = new ws.Server({ noServer: true }) @@ -1069,9 +1070,11 @@ async function startWatcher(opts: SetupOpts) { .map((param: string) => decodeURIComponent(param)) .join('/')}` + const denormalizedPagePath = denormalizePagePath(decodedPagePath) + await hotReloader .ensurePage({ - page: decodedPagePath, + page: denormalizedPagePath, clientOnly: false, definition: undefined, }) From ebebb6a96a7988d3dd7f80f117bf9143497298c2 Mon Sep 17 00:00:00 2001 From: Jimmy Lai Date: Thu, 12 Oct 2023 10:55:52 +0200 Subject: [PATCH 04/25] CI: add manual workflow for running e2e on prod (#56738) This PR adds a job to the `build-and-deploy` workflow so that we run e2e tests on production/vercel if the job was dispatched manually. This is useful if you need to double-check your PR since we don't run them on production for every PRs. --- .github/workflows/build_and_deploy.yml | 34 ++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/.github/workflows/build_and_deploy.yml b/.github/workflows/build_and_deploy.yml index 93648a7ae05c5..5257ca560fb79 100644 --- a/.github/workflows/build_and_deploy.yml +++ b/.github/workflows/build_and_deploy.yml @@ -511,6 +511,40 @@ jobs: jrm ./nextjs-test-result-junit.xml "test/test-junit-report/**/*.xml" DD_ENV=ci datadog-ci junit upload --tags test.type:nextjs_deploy_e2e --service nextjs ./nextjs-test-result-junit.xml + manualTestDeployE2E: + name: E2E (manual deploy) + runs-on: ubuntu-latest + if: ${{ github.event_name == 'workflow_dispatch' }} + needs: + - build + - build-wasm + - build-native + env: + NEXT_TELEMETRY_DISABLED: 1 + VERCEL_TEST_TOKEN: ${{ secrets.VERCEL_TEST_TOKEN }} + VERCEL_TEST_TEAM: vtest314-next-e2e-tests + DATADOG_API_KEY: ${{ secrets.DATA_DOG_API_KEY }} + steps: + - uses: actions/cache@v3 + timeout-minutes: 5 + id: restore-build + with: + path: ./* + key: ${{ github.sha }}-${{ github.run_number }} + + - run: npm i -g vercel@latest + + - uses: actions/download-artifact@v3 + with: + name: next-swc-binaries + path: packages/next-swc/native + + - run: RESET_VC_PROJECT=true node scripts/reset-vercel-project.mjs + name: Reset test project + + - run: docker run --rm -v $(pwd):/work mcr.microsoft.com/playwright:v1.35.1-jammy /bin/bash -c "cd /work && NODE_VERSION=${{ env.NODE_LTS_VERSION }} ./scripts/setup-node.sh && corepack enable > /dev/null && DATADOG_TRACE_NEXTJS_TEST=TRUE DATADOG_API_KEY=${DATADOG_API_KEY} DD_ENV=ci VERCEL_TEST_TOKEN=${{ secrets.VERCEL_TEST_TOKEN }} VERCEL_TEST_TEAM=vtest314-next-e2e-tests NEXT_TEST_JOB=1 NEXT_TEST_MODE=deploy TEST_TIMINGS_TOKEN=${{ secrets.TEST_TIMINGS_TOKEN }} NEXT_TEST_CONTINUE_ON_ERROR=1 xvfb-run node run-tests.js --type e2e >> /proc/1/fd/1" + name: Run test/e2e (deploy) + releaseStats: name: Release Stats runs-on: From 3bb80cfb83a2a76363a1544ea8a15f43a3e3f836 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 12 Oct 2023 14:59:26 +0200 Subject: [PATCH 05/25] Improve chunk encoding test to check right path for Turbopack (#56747) This only fixes the test check, Turbopack wil have to `encodeURI` the files in the FlightManifest. Similar to what the webpack plugin does: https://github.com/vercel/next.js/blob/canary/packages/next/src/build/webpack/plugins/flight-manifest-plugin.ts#L111 --- test/e2e/app-dir/app/index.test.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/e2e/app-dir/app/index.test.ts b/test/e2e/app-dir/app/index.test.ts index 381f823495569..b80031f945a6d 100644 --- a/test/e2e/app-dir/app/index.test.ts +++ b/test/e2e/app-dir/app/index.test.ts @@ -13,7 +13,7 @@ createNextDescribe( ? 'pnpm next experimental-compile' : undefined, }, - ({ next, isNextDev: isDev, isNextStart, isNextDeploy }) => { + ({ next, isNextDev: isDev, isNextStart, isNextDeploy, isTurbopack }) => { if (process.env.NEXT_EXPERIMENTAL_COMPILE) { it('should provide query for getStaticProps page correctly', async () => { const res = await next.fetch('/ssg?hello=world') @@ -192,10 +192,13 @@ createNextDescribe( await check(async () => { return requests.some( (req) => - req.includes(encodeURI('/[category]/[id]')) && req.endsWith('.js') + req.includes( + encodeURI(isTurbopack ? '[category]_[id]' : '/[category]/[id]') + ) && req.endsWith('.js') ) ? 'found' - : JSON.stringify(requests) + : // When it fails will log out the paths. + JSON.stringify(requests) }, 'found') }) From b6cce9ce5e0bdb7b3dda21e0ab67b3fcbb741a9f Mon Sep 17 00:00:00 2001 From: Delba de Oliveira <32464864+delbaoliveira@users.noreply.github.com> Date: Thu, 12 Oct 2023 14:16:06 +0100 Subject: [PATCH 06/25] Docs: Add missing description field (#56749) Fixing error in next-site due to empty description field. --- .../05-next-config-js/optimizePackageImports.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/02-app/02-api-reference/05-next-config-js/optimizePackageImports.mdx b/docs/02-app/02-api-reference/05-next-config-js/optimizePackageImports.mdx index 2d1a5c1f538ca..7f33802a0c77a 100644 --- a/docs/02-app/02-api-reference/05-next-config-js/optimizePackageImports.mdx +++ b/docs/02-app/02-api-reference/05-next-config-js/optimizePackageImports.mdx @@ -1,6 +1,6 @@ --- title: optimizePackageImports -description: +description: API Reference for optmizedPackageImports Next.js Config Option --- {/* The content of this doc is shared between the app and pages router. You can use the `Content` component to add content that is specific to the Pages Router. Any shared content should not be wrapped in a component. */} From 62ab0e33a2988989c67b9b7e429874d4cbc0473f Mon Sep 17 00:00:00 2001 From: Jimmy Lai Date: Thu, 12 Oct 2023 15:57:09 +0200 Subject: [PATCH 07/25] ci: add job summary to the test suite runs (#56742) This PR adds Github Actions summaries to the test suite that runs in the CI so that you can easily visualise which tests failed + what the relevant log was instead of parsing the logs yourself. Example here https://github.com/vercel/next.js/actions/runs/6495658699 ![CleanShot 2023-10-12 at 14 57 32@2x](https://github.com/vercel/next.js/assets/11064311/7d65496b-6e28-460a-8bef-3f2e91266d00) --- package.json | 1 + pnpm-lock.yaml | 34 +++++++++++++++++++++++++++++++++ run-tests.js | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+) diff --git a/package.json b/package.json index 6d854c552f15d..1ffad6d76e11e 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "update-google-fonts": "node ./scripts/update-google-fonts.js" }, "devDependencies": { + "@actions/core": "1.10.1", "@babel/core": "7.18.0", "@babel/eslint-parser": "7.18.2", "@babel/generator": "7.18.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6db612a66bd21..53fa9069b9ea1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,6 +20,9 @@ importers: .: devDependencies: + '@actions/core': + specifier: 1.10.1 + version: 1.10.1 '@babel/core': specifier: 7.18.0 version: 7.18.0 @@ -1594,6 +1597,20 @@ importers: packages: + /@actions/core@1.10.1: + resolution: {integrity: sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==} + dependencies: + '@actions/http-client': 2.2.0 + uuid: 8.3.2 + dev: true + + /@actions/http-client@2.2.0: + resolution: {integrity: sha512-q+epW0trjVUUHboliPb4UF9g2msf+w61b32tAkFEwL/IwP0DQWgbCMM0Hbe3e3WXSKz5VcUXbzJQgy8Hkra/Lg==} + dependencies: + tunnel: 0.0.6 + undici: 5.26.3 + dev: true + /@adobe/css-tools@4.3.1: resolution: {integrity: sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg==} dev: true @@ -5225,6 +5242,11 @@ packages: - supports-color dev: false + /@fastify/busboy@2.0.0: + resolution: {integrity: sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==} + engines: {node: '>=14'} + dev: true + /@firebase/analytics-types@0.3.1: resolution: {integrity: sha512-63vVJ5NIBh/JF8l9LuPrQYSzFimk7zYHySQB4Dk9rVdJ8kV/vGQoVTvRu1UW05sEc2Ug5PqtEChtTHU+9hvPcA==} dev: true @@ -25341,6 +25363,11 @@ packages: safe-buffer: 5.2.1 dev: true + /tunnel@0.0.6: + resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} + engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} + dev: true + /turbo-darwin-64@1.10.9: resolution: {integrity: sha512-Avz3wsYYb8/vjyHPVRFbNbowIiaF33vcBRklIUkPchTLvZekrT5x3ltQBCflyoi2zJV9g08hK4xXTGuCxeVvPA==} cpu: [x64] @@ -25583,6 +25610,13 @@ packages: busboy: 1.6.0 dev: true + /undici@5.26.3: + resolution: {integrity: sha512-H7n2zmKEWgOllKkIUkLvFmsJQj062lSm3uA4EYApG8gLuiOM0/go9bIoC3HVaSnfg4xunowDE2i9p8drkXuvDw==} + engines: {node: '>=14.0'} + dependencies: + '@fastify/busboy': 2.0.0 + dev: true + /unfetch@4.2.0: resolution: {integrity: sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==} dev: true diff --git a/run-tests.js b/run-tests.js index b6178477b0691..23c73a83b2fc0 100644 --- a/run-tests.js +++ b/run-tests.js @@ -11,6 +11,7 @@ const { spawn, exec: execOrig } = require('child_process') const { createNextInstall } = require('./test/lib/create-next-install') const glob = promisify(_glob) const exec = promisify(execOrig) +const core = require('@actions/core') function escapeRegexp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') @@ -73,6 +74,45 @@ const mockTrace = () => ({ // which types we have configured to run separate const configuredTestTypes = Object.values(testFilters) +const errorsPerTests = new Map() + +async function maybeLogSummary() { + if (process.env.CI && errorsPerTests.size > 0) { + const outputTemplate = ` +${Array.from(errorsPerTests.entries()) + .map(([test, output]) => { + return ` +
+${test} + +\`\`\` +${output} +\`\`\` + +
+` + }) + .join('\n')}` + + await core.summary + .addHeading('Tests failures') + .addTable([ + [ + { + data: 'Test suite', + header: true, + }, + ], + ...Array.from(errorsPerTests.entries()).map(([test]) => { + return [ + `${test}`, + ] + }), + ]) + .addRaw(outputTemplate) + .write() + } +} const cleanUpAndExit = async (code) => { if (process.env.NEXT_TEST_STARTER) { @@ -81,6 +121,9 @@ const cleanUpAndExit = async (code) => { if (process.env.NEXT_TEST_TEMP_REPO) { await fs.remove(process.env.NEXT_TEST_TEMP_REPO) } + if (process.env.CI) { + await maybeLogSummary() + } console.log(`exiting with code ${code}`) setTimeout(() => { @@ -472,11 +515,19 @@ ${ENDGROUP}`) } else { process.stdout.write(`${GROUP}❌ ${test.file} output\n`) } + + let output = '' // limit out to last 64kb so that we don't // run out of log room in CI for (const { chunk } of outputChunks) { process.stdout.write(chunk) + output += chunk.toString() } + + if (process.env.CI && !killed) { + errorsPerTests.set(test.file, output) + } + if (isExpanded) { process.stdout.write(`end of ${test.file} output\n`) } else { From 6814ff147a416a437c541fd2a27e69e1794af700 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Thu, 12 Oct 2023 18:10:55 +0200 Subject: [PATCH 08/25] Prefer module over main on main fields for app router server compiler (#56532) This change is to pick the esm assets for RSC server layer and server rendering side, this is for production and development perf purpose, also to let them apply with the ESM related optimization such as tree-shaking, barrel files optimizations, etc. We found a few packages that can't be optimized easily in bundling because we're using "main" field so the packages are not able to be tree-shaked, ending up with large bundle in the dist. This will change a lot for the bundling improvements as some packages are only having "main" and "module" field. So switching from CJS to ESM means better bundling, more optimization, and faster code. #56501 was a precondition for this, as previously the bundling strategy was applied to some library but triggered the invalid hooks erroring. ### Other Monior Change Previously we'll prefer to resolve CJS as there're 2 versions of react, using CJS assets will help let them pass by require-hook to use canary react for app router bundling assets. But now we changed the approach to bundling nextjs runtime and react packages. Now we dropped the condition that prefered to resolve CJS exports for externals, since if you're putting them in `serverComponentsExternalPackages`, they're not using the built-in react, so could potentially having trouble if any dependency is using react but excluded in bundles. So far we didn't see any report to this. Closes NEXT-1286 --- packages/next/src/build/handle-externals.ts | 11 +---- .../src/build/webpack-config-rules/resolve.ts | 40 +++++++++++++++++++ packages/next/src/build/webpack-config.ts | 27 +++++-------- .../plugins/next-trace-entrypoints-plugin.ts | 1 - .../app-dir/app-external/app-external.test.ts | 38 +++++++++--------- .../react-server/3rd-party-package/page.js | 3 ++ .../app/react-server/optout/page.js | 4 ++ .../conditional-exports-optout/package.json | 3 ++ .../conditional-exports-optout/react.js | 5 +++ .../conditional-exports/package.json | 3 ++ .../conditional-exports/react.js | 5 +++ .../server-module-field/index.cjs | 1 + .../server-module-field/index.esm.js | 1 + .../server-module-field/package.json | 4 ++ 14 files changed, 99 insertions(+), 47 deletions(-) create mode 100644 packages/next/src/build/webpack-config-rules/resolve.ts create mode 100644 test/e2e/app-dir/app-external/node_modules_bak/conditional-exports-optout/react.js create mode 100644 test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/react.js create mode 100644 test/e2e/app-dir/app-external/node_modules_bak/server-module-field/index.cjs create mode 100644 test/e2e/app-dir/app-external/node_modules_bak/server-module-field/index.esm.js create mode 100644 test/e2e/app-dir/app-external/node_modules_bak/server-module-field/package.json diff --git a/packages/next/src/build/handle-externals.ts b/packages/next/src/build/handle-externals.ts index 2e0eb816b1495..853ab2e3c68ab 100644 --- a/packages/next/src/build/handle-externals.ts +++ b/packages/next/src/build/handle-externals.ts @@ -44,7 +44,6 @@ export async function resolveExternal( context: string, request: string, isEsmRequested: boolean, - hasAppDir: boolean, getResolve: ( options: any ) => ( @@ -66,11 +65,7 @@ export async function resolveExternal( let preferEsmOptions = esmExternals && isEsmRequested ? [true, false] : [false] - // Disable esm resolving for app/ and pages/ so for esm package using under pages/ - // won't load react through esm loader - if (hasAppDir) { - preferEsmOptions = [false] - } + for (const preferEsm of preferEsmOptions) { const resolve = getResolve( preferEsm ? esmResolveOptions : nodeResolveOptions @@ -135,12 +130,10 @@ export function makeExternalHandler({ config, optOutBundlingPackageRegex, dir, - hasAppDir, }: { config: NextConfigComplete optOutBundlingPackageRegex: RegExp dir: string - hasAppDir: boolean }) { let resolvedExternalPackageDirs: Map const looseEsmExternals = config.experimental?.esmExternals === 'loose' @@ -293,7 +286,6 @@ export function makeExternalHandler({ context, request, isEsmRequested, - hasAppDir, getResolve, isLocal ? resolveNextExternal : undefined ) @@ -353,7 +345,6 @@ export function makeExternalHandler({ config.experimental.esmExternals, context, pkg + '/package.json', - hasAppDir, isEsmRequested, getResolve, isLocal ? resolveNextExternal : undefined diff --git a/packages/next/src/build/webpack-config-rules/resolve.ts b/packages/next/src/build/webpack-config-rules/resolve.ts new file mode 100644 index 0000000000000..f50f6c92ee629 --- /dev/null +++ b/packages/next/src/build/webpack-config-rules/resolve.ts @@ -0,0 +1,40 @@ +import { + COMPILER_NAMES, + type CompilerNameValues, +} from '../../shared/lib/constants' + +// exports. +export const edgeConditionNames = [ + 'edge-light', + 'worker', + // inherits the default conditions + '...', +] + +const mainFieldsPerCompiler: Record< + CompilerNameValues | 'app-router-server', + string[] +> = { + // For default case, prefer CJS over ESM on server side. e.g. pages dir SSR + [COMPILER_NAMES.server]: ['main', 'module'], + [COMPILER_NAMES.client]: ['browser', 'module', 'main'], + [COMPILER_NAMES.edgeServer]: edgeConditionNames, + // For app router since everything is bundled, prefer ESM over CJS + 'app-router-server': ['module', 'main'], +} + +export function getMainField( + pageType: 'app' | 'pages', + compilerType: CompilerNameValues +) { + if (compilerType === COMPILER_NAMES.edgeServer) { + return edgeConditionNames + } else if (compilerType === COMPILER_NAMES.client) { + return mainFieldsPerCompiler[COMPILER_NAMES.client] + } + + // Prefer module fields over main fields for isomorphic packages on server layer + return pageType === 'app' + ? mainFieldsPerCompiler['app-router-server'] + : mainFieldsPerCompiler[COMPILER_NAMES.server] +} diff --git a/packages/next/src/build/webpack-config.ts b/packages/next/src/build/webpack-config.ts index 1664d4377787c..a20cf97a1e97f 100644 --- a/packages/next/src/build/webpack-config.ts +++ b/packages/next/src/build/webpack-config.ts @@ -74,6 +74,10 @@ import { needsExperimentalReact } from '../lib/needs-experimental-react' import { getDefineEnvPlugin } from './webpack/plugins/define-env-plugin' import type { SWCLoaderOptions } from './webpack/loaders/next-swc-loader' import { isResourceInPackages, makeExternalHandler } from './handle-externals' +import { + getMainField, + edgeConditionNames, +} from './webpack-config-rules/resolve' type ExcludesFalse = (x: T | false) => x is T type ClientEntries = { @@ -104,21 +108,6 @@ const babelIncludeRegexes: RegExp[] = [ const asyncStoragesRegex = /next[\\/]dist[\\/](esm[\\/])?client[\\/]components[\\/](static-generation-async-storage|action-async-storage|request-async-storage)/ -// exports. -const edgeConditionNames = [ - 'edge-light', - 'worker', - // inherits the default conditions - '...', -] - -// packageJson. -const mainFieldsPerCompiler: Record = { - [COMPILER_NAMES.server]: ['main', 'module'], - [COMPILER_NAMES.client]: ['browser', 'module', 'main'], - [COMPILER_NAMES.edgeServer]: edgeConditionNames, -} - // Support for NODE_PATH const nodePathList = (process.env.NODE_PATH || '') .split(process.platform === 'win32' ? ';' : ':') @@ -931,7 +920,8 @@ export default async function getBaseWebpackConfig( }, } : undefined), - mainFields: mainFieldsPerCompiler[compilerType], + // default main fields use pages dir ones, and customize app router ones in loaders. + mainFields: getMainField('pages', compilerType), ...(isEdgeServer && { conditionNames: edgeConditionNames, }), @@ -1039,7 +1029,6 @@ export default async function getBaseWebpackConfig( config, optOutBundlingPackageRegex, dir, - hasAppDir, }) const shouldIncludeExternalDirs = @@ -1610,6 +1599,7 @@ export default async function getBaseWebpackConfig( ], }, resolve: { + mainFields: getMainField('app', compilerType), conditionNames: reactServerCondition, // If missing the alias override here, the default alias will be used which aliases // react to the direct file path, not the package name. In that case the condition @@ -1754,6 +1744,9 @@ export default async function getBaseWebpackConfig( ], exclude: [codeCondition.exclude], use: swcLoaderForClientLayer, + resolve: { + mainFields: getMainField('app', compilerType), + }, }, ] : []), diff --git a/packages/next/src/build/webpack/plugins/next-trace-entrypoints-plugin.ts b/packages/next/src/build/webpack/plugins/next-trace-entrypoints-plugin.ts index 1f61d3520d29d..5ea193152a283 100644 --- a/packages/next/src/build/webpack/plugins/next-trace-entrypoints-plugin.ts +++ b/packages/next/src/build/webpack/plugins/next-trace-entrypoints-plugin.ts @@ -743,7 +743,6 @@ export class TraceEntryPointsPlugin implements webpack.WebpackPluginInstance { context, request, isEsmRequested, - !!this.appDirEnabled, (options) => (_: string, resRequest: string) => { return getResolve(options)(parent, resRequest, job) }, diff --git a/test/e2e/app-dir/app-external/app-external.test.ts b/test/e2e/app-dir/app-external/app-external.test.ts index 38592f5ba1b47..b4e66cb205966 100644 --- a/test/e2e/app-dir/app-external/app-external.test.ts +++ b/test/e2e/app-dir/app-external/app-external.test.ts @@ -39,7 +39,7 @@ createNextDescribe( buildCommand: 'yarn build', skipDeployment: true, }, - ({ next, isNextDev }) => { + ({ next }) => { it('should be able to opt-out 3rd party packages being bundled in server components', async () => { await next.fetch('/react-server/optout').then(async (response) => { const result = await resolveStreamResponse(response) @@ -47,6 +47,7 @@ createNextDescribe( expect(result).toContain('Server subpath: subpath.default') expect(result).toContain('Client: index.default') expect(result).toContain('Client subpath: subpath.default') + expect(result).toContain('opt-out-react-version: 18.2.0') }) }) @@ -91,24 +92,23 @@ createNextDescribe( }) it('should resolve 3rd party package exports based on the react-server condition', async () => { - await next - .fetch('/react-server/3rd-party-package') - .then(async (response) => { - const result = await resolveStreamResponse(response) - - // Package should be resolved based on the react-server condition, - // as well as package's internal & external dependencies. - expect(result).toContain( - 'Server: index.react-server:react.subset:dep.server' - ) - expect(result).toContain( - 'Client: index.default:react.full:dep.default' - ) - - // Subpath exports should be resolved based on the condition too. - expect(result).toContain('Server subpath: subpath.react-server') - expect(result).toContain('Client subpath: subpath.default') - }) + const $ = await next.render$('/react-server/3rd-party-package') + + const result = $('body').text() + + // Package should be resolved based on the react-server condition, + // as well as package's internal & external dependencies. + expect(result).toContain( + 'Server: index.react-server:react.subset:dep.server' + ) + expect(result).toContain('Client: index.default:react.full:dep.default') + + // Subpath exports should be resolved based on the condition too. + expect(result).toContain('Server subpath: subpath.react-server') + expect(result).toContain('Client subpath: subpath.default') + + // Prefer `module` field for isomorphic packages. + expect($('#main-field').text()).toContain('server-module-field:module') }) it('should correctly collect global css imports and mark them as side effects', async () => { diff --git a/test/e2e/app-dir/app-external/app/react-server/3rd-party-package/page.js b/test/e2e/app-dir/app-external/app/react-server/3rd-party-package/page.js index 33141e12f7685..92e9f01672faa 100644 --- a/test/e2e/app-dir/app-external/app/react-server/3rd-party-package/page.js +++ b/test/e2e/app-dir/app-external/app/react-server/3rd-party-package/page.js @@ -1,5 +1,6 @@ import v from 'conditional-exports' import v1 from 'conditional-exports/subpath' +import { name as serverFieldName } from 'server-module-field' import Client from './client' @@ -11,6 +12,8 @@ export default function Page() { {`Server subpath: ${v1}`}
+
+
{`Server module field: ${serverFieldName}`}
) } diff --git a/test/e2e/app-dir/app-external/app/react-server/optout/page.js b/test/e2e/app-dir/app-external/app/react-server/optout/page.js index fc7bd55ab86c3..45ba1ccff0358 100644 --- a/test/e2e/app-dir/app-external/app/react-server/optout/page.js +++ b/test/e2e/app-dir/app-external/app/react-server/optout/page.js @@ -1,5 +1,6 @@ import v from 'conditional-exports-optout' import v1 from 'conditional-exports-optout/subpath' +import { getReactVersion } from 'conditional-exports-optout/react' import Client from './client' @@ -11,6 +12,9 @@ export default function Page() { {`Server subpath: ${v1}`}
+

+ {`opt-out-react-version: ${getReactVersion()}`} +

) } diff --git a/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports-optout/package.json b/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports-optout/package.json index fe1b70d109b2a..3355c20aad28a 100644 --- a/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports-optout/package.json +++ b/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports-optout/package.json @@ -10,6 +10,9 @@ "react-server": "./subpath.server.js", "default": "./subpath.js" }, + "./react": { + "import": "./react.js" + }, "./package.json": "./package.json" } } diff --git a/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports-optout/react.js b/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports-optout/react.js new file mode 100644 index 0000000000000..4f2c2283ed693 --- /dev/null +++ b/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports-optout/react.js @@ -0,0 +1,5 @@ +import React from 'react' + +export function getReactVersion() { + return React.version +} diff --git a/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/package.json b/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/package.json index b51ade2e7acfe..06e09e177ae16 100644 --- a/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/package.json +++ b/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/package.json @@ -16,6 +16,9 @@ "react-server": "./subpath.server.js", "default": "./subpath.js" }, + "./react": { + "import": "./react.js" + }, "./package.json": "./package.json" } } diff --git a/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/react.js b/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/react.js new file mode 100644 index 0000000000000..4f2c2283ed693 --- /dev/null +++ b/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/react.js @@ -0,0 +1,5 @@ +import React from 'react' + +export function getReactVersion() { + return React.version +} diff --git a/test/e2e/app-dir/app-external/node_modules_bak/server-module-field/index.cjs b/test/e2e/app-dir/app-external/node_modules_bak/server-module-field/index.cjs new file mode 100644 index 0000000000000..bead07e159aa3 --- /dev/null +++ b/test/e2e/app-dir/app-external/node_modules_bak/server-module-field/index.cjs @@ -0,0 +1 @@ +exports.name = 'server-module-field:main' diff --git a/test/e2e/app-dir/app-external/node_modules_bak/server-module-field/index.esm.js b/test/e2e/app-dir/app-external/node_modules_bak/server-module-field/index.esm.js new file mode 100644 index 0000000000000..02218634f7d07 --- /dev/null +++ b/test/e2e/app-dir/app-external/node_modules_bak/server-module-field/index.esm.js @@ -0,0 +1 @@ +export const name = 'server-module-field:module' diff --git a/test/e2e/app-dir/app-external/node_modules_bak/server-module-field/package.json b/test/e2e/app-dir/app-external/node_modules_bak/server-module-field/package.json new file mode 100644 index 0000000000000..d6cb0ed97cb3d --- /dev/null +++ b/test/e2e/app-dir/app-external/node_modules_bak/server-module-field/package.json @@ -0,0 +1,4 @@ +{ + "main": "./index.cjs", + "module": "./index.esm.js" +} From a5d34d53f8b118ef97935a08fe1c960bd3ea9503 Mon Sep 17 00:00:00 2001 From: Mayank Kamboj Date: Thu, 12 Oct 2023 21:44:08 +0530 Subject: [PATCH 09/25] change those->some for clarity (#56688) --- contributing/repository/linting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contributing/repository/linting.md b/contributing/repository/linting.md index 513797ce7e280..30535fdd6d0cf 100644 --- a/contributing/repository/linting.md +++ b/contributing/repository/linting.md @@ -14,7 +14,7 @@ If you get errors, you can run the ESLint and Prettier auto-fix using: pnpm lint-fix ``` -Not all rules can be auto-fixed, those require manual changes. +Not all rules can be auto-fixed, some require manual changes. If you get a warning by alex, follow the instructions to correct the language. From 6fdba20b6d11fa6be459dc26214e6bbeb0c37652 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Orb=C3=A1n?= Date: Thu, 12 Oct 2023 18:18:20 +0200 Subject: [PATCH 10/25] docs: fix typo in Update 02-get-static-paths.mdx (#56757) Fix typo in docs Fixes #56741 Co-authored-by: JJ Kasper --- .../03-data-fetching/02-get-static-paths.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/03-pages/01-building-your-application/03-data-fetching/02-get-static-paths.mdx b/docs/03-pages/01-building-your-application/03-data-fetching/02-get-static-paths.mdx index 4d00624c3f98c..77e74f5ead92f 100644 --- a/docs/03-pages/01-building-your-application/03-data-fetching/02-get-static-paths.mdx +++ b/docs/03-pages/01-building-your-application/03-data-fetching/02-get-static-paths.mdx @@ -1,6 +1,6 @@ --- title: getStaticPaths -description: Fetch data and generate static pages with `getStaticProps`. Learn more about this API for data fetching in Next.js. +description: Fetch data and generate static pages with `getStaticPaths`. Learn more about this API for data fetching in Next.js. --- If a page has [Dynamic Routes](/docs/pages/building-your-application/routing/dynamic-routes) and uses `getStaticProps`, it needs to define a list of paths to be statically generated. From 0a6c60cec66b59e71f05c3ab15c28363b66ecf85 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Thu, 12 Oct 2023 09:34:27 -0700 Subject: [PATCH 11/25] Break out E2E deploy test workflow to its own (#56755) As discussed with @feedthejim this breaks our E2E deploy tests workflow into it's own so it can be triggered on cron/manually easier. One thing we'll need to consider with the cron/manual workflow is if a canary isn't published yet and Next.js relies on swc changes it will fail since this doesn't pack/publish a fresh built swc binary currently. --- .github/workflows/build_and_deploy.yml | 82 -------------------------- .github/workflows/test_e2e_deploy.yml | 80 +++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 82 deletions(-) create mode 100644 .github/workflows/test_e2e_deploy.yml diff --git a/.github/workflows/build_and_deploy.yml b/.github/workflows/build_and_deploy.yml index 5257ca560fb79..0547c39f95d7f 100644 --- a/.github/workflows/build_and_deploy.yml +++ b/.github/workflows/build_and_deploy.yml @@ -463,88 +463,6 @@ jobs: VERCEL_API_TOKEN: ${{ secrets.VERCEL_API_TOKEN }} DEPLOY_ENVIRONMENT: production - testDeployE2E: - name: E2E (deploy) - runs-on: ubuntu-latest - needs: [publishRelease] - env: - NEXT_TELEMETRY_DISABLED: 1 - VERCEL_TEST_TOKEN: ${{ secrets.VERCEL_TEST_TOKEN }} - VERCEL_TEST_TEAM: vtest314-next-e2e-tests - DATADOG_API_KEY: ${{ secrets.DATA_DOG_API_KEY }} - steps: - - uses: actions/cache@v3 - timeout-minutes: 5 - id: restore-build - with: - path: ./* - key: ${{ github.sha }}-${{ github.run_number }} - - - run: npm i -g vercel@latest - - - uses: actions/download-artifact@v3 - with: - name: next-swc-binaries - path: packages/next-swc/native - - - run: RESET_VC_PROJECT=true node scripts/reset-vercel-project.mjs - name: Reset test project - - - run: docker run --rm -v $(pwd):/work mcr.microsoft.com/playwright:v1.35.1-jammy /bin/bash -c "cd /work && NODE_VERSION=${{ env.NODE_LTS_VERSION }} ./scripts/setup-node.sh && corepack enable > /dev/null && DATADOG_TRACE_NEXTJS_TEST=TRUE DATADOG_API_KEY=${DATADOG_API_KEY} DD_ENV=ci VERCEL_TEST_TOKEN=${{ secrets.VERCEL_TEST_TOKEN }} VERCEL_TEST_TEAM=vtest314-next-e2e-tests NEXT_TEST_JOB=1 NEXT_TEST_MODE=deploy TEST_TIMINGS_TOKEN=${{ secrets.TEST_TIMINGS_TOKEN }} NEXT_TEST_CONTINUE_ON_ERROR=1 xvfb-run node run-tests.js --type e2e >> /proc/1/fd/1" - name: Run test/e2e (deploy) - - - name: Upload test trace - if: always() - uses: actions/upload-artifact@v3 - with: - name: test-trace - if-no-files-found: ignore - retention-days: 2 - path: | - test/traces - - - name: Upload test trace to datadog - continue-on-error: true - run: | - ls -al ./test - npm install -g junit-report-merger@6.0.2 @datadog/datadog-ci@2.14.0 @aws-sdk/property-provider@3 - jrm ./nextjs-test-result-junit.xml "test/test-junit-report/**/*.xml" - DD_ENV=ci datadog-ci junit upload --tags test.type:nextjs_deploy_e2e --service nextjs ./nextjs-test-result-junit.xml - - manualTestDeployE2E: - name: E2E (manual deploy) - runs-on: ubuntu-latest - if: ${{ github.event_name == 'workflow_dispatch' }} - needs: - - build - - build-wasm - - build-native - env: - NEXT_TELEMETRY_DISABLED: 1 - VERCEL_TEST_TOKEN: ${{ secrets.VERCEL_TEST_TOKEN }} - VERCEL_TEST_TEAM: vtest314-next-e2e-tests - DATADOG_API_KEY: ${{ secrets.DATA_DOG_API_KEY }} - steps: - - uses: actions/cache@v3 - timeout-minutes: 5 - id: restore-build - with: - path: ./* - key: ${{ github.sha }}-${{ github.run_number }} - - - run: npm i -g vercel@latest - - - uses: actions/download-artifact@v3 - with: - name: next-swc-binaries - path: packages/next-swc/native - - - run: RESET_VC_PROJECT=true node scripts/reset-vercel-project.mjs - name: Reset test project - - - run: docker run --rm -v $(pwd):/work mcr.microsoft.com/playwright:v1.35.1-jammy /bin/bash -c "cd /work && NODE_VERSION=${{ env.NODE_LTS_VERSION }} ./scripts/setup-node.sh && corepack enable > /dev/null && DATADOG_TRACE_NEXTJS_TEST=TRUE DATADOG_API_KEY=${DATADOG_API_KEY} DD_ENV=ci VERCEL_TEST_TOKEN=${{ secrets.VERCEL_TEST_TOKEN }} VERCEL_TEST_TEAM=vtest314-next-e2e-tests NEXT_TEST_JOB=1 NEXT_TEST_MODE=deploy TEST_TIMINGS_TOKEN=${{ secrets.TEST_TIMINGS_TOKEN }} NEXT_TEST_CONTINUE_ON_ERROR=1 xvfb-run node run-tests.js --type e2e >> /proc/1/fd/1" - name: Run test/e2e (deploy) - releaseStats: name: Release Stats runs-on: diff --git a/.github/workflows/test_e2e_deploy.yml b/.github/workflows/test_e2e_deploy.yml new file mode 100644 index 0000000000000..0d86aa03f2f61 --- /dev/null +++ b/.github/workflows/test_e2e_deploy.yml @@ -0,0 +1,80 @@ +name: test-e2e-deploy + +on: + schedule: + # run every day at midnight + - cron: '0 0 * * *' + # allow triggering manually as well + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + env: + VERCEL_TEST_TOKEN: ${{ secrets.VERCEL_TEST_TOKEN }} + VERCEL_TEST_TEAM: vtest314-next-e2e-tests + DATADOG_API_KEY: ${{ secrets.DATA_DOG_API_KEY }} + NAPI_CLI_VERSION: 2.16.2 + TURBO_VERSION: 1.10.9 + NODE_MAINTENANCE_VERSION: 16 + NODE_LTS_VERSION: 18 + CARGO_PROFILE_RELEASE_LTO: 'true' + TURBO_TEAM: 'vercel' + TURBO_REMOTE_ONLY: 'true' + TEST_TIMINGS_TOKEN: ${{ secrets.TEST_TIMINGS_TOKEN }} + NEXT_TELEMETRY_DISABLED: 1 + # we build a dev binary for use in CI so skip downloading + # canary next-swc binaries in the monorepo + NEXT_SKIP_NATIVE_POSTINSTALL: 1 + + strategy: + fail-fast: false + matrix: + group: [1, 2] + + steps: + - name: Setup node + uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_LTS_VERSION }} + check-latest: true + - run: corepack enable + + - uses: actions/checkout@v3 + with: + fetch-depth: 25 + + - run: pnpm install + + - run: pnpm run build + + - run: npm i -g vercel@latest + + - uses: actions/download-artifact@v3 + with: + name: next-swc-binaries + path: packages/next-swc/native + + - run: RESET_VC_PROJECT=true node scripts/reset-vercel-project.mjs + name: Reset test project + + - run: docker run --rm -v $(pwd):/work mcr.microsoft.com/playwright:v1.35.1-jammy /bin/bash -c "cd /work && NODE_VERSION=${{ env.NODE_LTS_VERSION }} ./scripts/setup-node.sh && corepack enable > /dev/null && DATADOG_TRACE_NEXTJS_TEST=TRUE DATADOG_API_KEY=${DATADOG_API_KEY} DD_ENV=ci VERCEL_TEST_TOKEN=${{ secrets.VERCEL_TEST_TOKEN }} VERCEL_TEST_TEAM=vtest314-next-e2e-tests NEXT_TEST_JOB=1 NEXT_TEST_MODE=deploy TEST_TIMINGS_TOKEN=${{ secrets.TEST_TIMINGS_TOKEN }} NEXT_TEST_CONTINUE_ON_ERROR=1 xvfb-run node run-tests.js --type e2e --timings -g ${{ matrix.group }}/2 -c 2 >> /proc/1/fd/1" + name: Run test/e2e (deploy) + + - name: Upload test trace + if: always() + uses: actions/upload-artifact@v3 + with: + name: test-trace + if-no-files-found: ignore + retention-days: 2 + path: | + test/traces + + - name: Upload test trace to datadog + continue-on-error: true + run: | + ls -al ./test + npm install -g junit-report-merger@6.0.2 @datadog/datadog-ci@2.14.0 @aws-sdk/property-provider@3 + jrm ./nextjs-test-result-junit.xml "test/test-junit-report/**/*.xml" + DD_ENV=ci datadog-ci junit upload --tags test.type:nextjs_deploy_e2e --service nextjs ./nextjs-test-result-junit.xml From e057c26329e98315887901997f60e8d2ee8cc6bf Mon Sep 17 00:00:00 2001 From: Shu Ding Date: Thu, 12 Oct 2023 18:43:31 +0200 Subject: [PATCH 12/25] Check origins of Server Action requests (#56753) This check ensures that the `x-forwarded-host` (fallbacks to `host` if missing) header matches the request's `origin` header. --- .../src/server/app-render/action-handler.ts | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/packages/next/src/server/app-render/action-handler.ts b/packages/next/src/server/app-render/action-handler.ts index e8d9e136766b6..05d1a88e9b74b 100644 --- a/packages/next/src/server/app-render/action-handler.ts +++ b/packages/next/src/server/app-render/action-handler.ts @@ -286,6 +286,49 @@ export async function handleAction({ return } + const originHostname = + typeof req.headers['origin'] === 'string' + ? new URL(req.headers['origin']).host + : undefined + const host = req.headers['x-forwarded-host'] || req.headers['host'] + + // This is to prevent CSRF attacks. If `x-forwarded-host` is set, we need to + // ensure that the request is coming from the same host. + if (!originHostname) { + // This might be an old browser that doesn't send `host` header. We ignore + // this case. + console.warn( + 'Missing `origin` header from a forwarded Server Actions request.' + ) + } else if (!host || originHostname !== host) { + // This is an attack. We should not proceed the action. + console.error( + '`x-forwarded-host` and `host` headers do not match `origin` header from a forwarded Server Actions request. Aborting the action.' + ) + + const error = new Error('Invalid Server Actions request.') + + if (isFetchAction) { + res.statusCode = 500 + await Promise.all(staticGenerationStore.pendingRevalidates || []) + const promise = Promise.reject(error) + try { + await promise + } catch {} + + return { + type: 'done', + result: await generateFlight(ctx, { + actionResult: promise, + // if the page was not revalidated, we can skip the rendering the flight tree + skipFlight: !staticGenerationStore.pathWasRevalidated, + }), + } + } + + throw error + } + // ensure we avoid caching server actions unexpectedly res.setHeader( 'Cache-Control', From 5004c8c50c24ff8be4f54ccafbdbfff9179504c3 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Thu, 12 Oct 2023 10:12:24 -0700 Subject: [PATCH 13/25] Trigger canary release nightly (#56758) Follow-up to https://github.com/vercel/next.js/pull/56755 this updates to trigger at least one canary nightly before we run our E2E deploy tests. --- .github/workflows/trigger_release.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/trigger_release.yml b/.github/workflows/trigger_release.yml index b79df5057f19b..6faec5b1c37ea 100644 --- a/.github/workflows/trigger_release.yml +++ b/.github/workflows/trigger_release.yml @@ -1,4 +1,8 @@ on: + schedule: + # run every day at 23:15 + - cron: '15 23 * * *' + workflow_dispatch: inputs: releaseType: @@ -38,7 +42,7 @@ jobs: # canary next-swc binaries in the monorepo NEXT_SKIP_NATIVE_POSTINSTALL: 1 - environment: release-${{ github.event.inputs.releaseType }} + environment: release-${{ github.event.inputs.releaseType || 'canary' }} steps: - name: Setup node uses: actions/setup-node@v3 @@ -73,6 +77,6 @@ jobs: - run: pnpm run build - - run: node ./scripts/start-release.js --release-type ${{ github.event.inputs.releaseType }} --semver-type ${{ github.event.inputs.semverType }} + - run: node ./scripts/start-release.js --release-type ${{ github.event.inputs.releaseType || 'canary' }} --semver-type ${{ github.event.inputs.semverType }} env: RELEASE_BOT_GITHUB_TOKEN: ${{ secrets.RELEASE_BOT_GITHUB_TOKEN }} From 8013ef7372fc545d49dbd060461224ceb563b454 Mon Sep 17 00:00:00 2001 From: vercel-release-bot Date: Thu, 12 Oct 2023 17:27:01 +0000 Subject: [PATCH 14/25] v13.5.5-canary.9 --- lerna.json | 2 +- packages/create-next-app/package.json | 2 +- packages/eslint-config-next/package.json | 4 ++-- packages/eslint-plugin-next/package.json | 2 +- packages/font/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-storybook/package.json | 2 +- packages/next-polyfill-module/package.json | 2 +- packages/next-polyfill-nomodule/package.json | 2 +- packages/next-swc/package.json | 2 +- packages/next/package.json | 14 +++++++------- packages/react-dev-overlay/package.json | 2 +- packages/react-refresh-utils/package.json | 2 +- packages/third-parties/package.json | 4 ++-- pnpm-lock.yaml | 16 ++++++++-------- 18 files changed, 33 insertions(+), 33 deletions(-) diff --git a/lerna.json b/lerna.json index f206a2e40eeea..82212d1d74eb0 100644 --- a/lerna.json +++ b/lerna.json @@ -16,5 +16,5 @@ "registry": "https://registry.npmjs.org/" } }, - "version": "13.5.5-canary.8" + "version": "13.5.5-canary.9" } diff --git a/packages/create-next-app/package.json b/packages/create-next-app/package.json index 0d1be5f989f6e..2e662421fe8fe 100644 --- a/packages/create-next-app/package.json +++ b/packages/create-next-app/package.json @@ -1,6 +1,6 @@ { "name": "create-next-app", - "version": "13.5.5-canary.8", + "version": "13.5.5-canary.9", "keywords": [ "react", "next", diff --git a/packages/eslint-config-next/package.json b/packages/eslint-config-next/package.json index c903d7a834af7..5e917b536b47c 100644 --- a/packages/eslint-config-next/package.json +++ b/packages/eslint-config-next/package.json @@ -1,6 +1,6 @@ { "name": "eslint-config-next", - "version": "13.5.5-canary.8", + "version": "13.5.5-canary.9", "description": "ESLint configuration used by Next.js.", "main": "index.js", "license": "MIT", @@ -10,7 +10,7 @@ }, "homepage": "https://nextjs.org/docs/app/building-your-application/configuring/eslint#eslint-config", "dependencies": { - "@next/eslint-plugin-next": "13.5.5-canary.8", + "@next/eslint-plugin-next": "13.5.5-canary.9", "@rushstack/eslint-patch": "^1.3.3", "@typescript-eslint/parser": "^5.4.2 || ^6.0.0", "eslint-import-resolver-node": "^0.3.6", diff --git a/packages/eslint-plugin-next/package.json b/packages/eslint-plugin-next/package.json index 2aa66d5e3f3f1..7da03da6fabfa 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": "13.5.5-canary.8", + "version": "13.5.5-canary.9", "description": "ESLint plugin for Next.js.", "main": "dist/index.js", "license": "MIT", diff --git a/packages/font/package.json b/packages/font/package.json index fe48890d9b94f..8e08e7804bae2 100644 --- a/packages/font/package.json +++ b/packages/font/package.json @@ -1,6 +1,6 @@ { "name": "@next/font", - "version": "13.5.5-canary.8", + "version": "13.5.5-canary.9", "repository": { "url": "vercel/next.js", "directory": "packages/font" diff --git a/packages/next-bundle-analyzer/package.json b/packages/next-bundle-analyzer/package.json index 71adbe990d867..08366e689174e 100644 --- a/packages/next-bundle-analyzer/package.json +++ b/packages/next-bundle-analyzer/package.json @@ -1,6 +1,6 @@ { "name": "@next/bundle-analyzer", - "version": "13.5.5-canary.8", + "version": "13.5.5-canary.9", "main": "index.js", "types": "index.d.ts", "license": "MIT", diff --git a/packages/next-codemod/package.json b/packages/next-codemod/package.json index 18e7af2b3a42d..9951d49e949f5 100644 --- a/packages/next-codemod/package.json +++ b/packages/next-codemod/package.json @@ -1,6 +1,6 @@ { "name": "@next/codemod", - "version": "13.5.5-canary.8", + "version": "13.5.5-canary.9", "license": "MIT", "repository": { "type": "git", diff --git a/packages/next-env/package.json b/packages/next-env/package.json index 1973040e9e337..651022ad8b73e 100644 --- a/packages/next-env/package.json +++ b/packages/next-env/package.json @@ -1,6 +1,6 @@ { "name": "@next/env", - "version": "13.5.5-canary.8", + "version": "13.5.5-canary.9", "keywords": [ "react", "next", diff --git a/packages/next-mdx/package.json b/packages/next-mdx/package.json index d7e327ad82820..b0bfd040cd3f1 100644 --- a/packages/next-mdx/package.json +++ b/packages/next-mdx/package.json @@ -1,6 +1,6 @@ { "name": "@next/mdx", - "version": "13.5.5-canary.8", + "version": "13.5.5-canary.9", "main": "index.js", "license": "MIT", "repository": { diff --git a/packages/next-plugin-storybook/package.json b/packages/next-plugin-storybook/package.json index a243a17e1eb47..db4c4a63240ea 100644 --- a/packages/next-plugin-storybook/package.json +++ b/packages/next-plugin-storybook/package.json @@ -1,6 +1,6 @@ { "name": "@next/plugin-storybook", - "version": "13.5.5-canary.8", + "version": "13.5.5-canary.9", "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 0e05455f45593..148fc7900d410 100644 --- a/packages/next-polyfill-module/package.json +++ b/packages/next-polyfill-module/package.json @@ -1,6 +1,6 @@ { "name": "@next/polyfill-module", - "version": "13.5.5-canary.8", + "version": "13.5.5-canary.9", "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 e2e5bd6e22b33..4277cc48f6a7d 100644 --- a/packages/next-polyfill-nomodule/package.json +++ b/packages/next-polyfill-nomodule/package.json @@ -1,6 +1,6 @@ { "name": "@next/polyfill-nomodule", - "version": "13.5.5-canary.8", + "version": "13.5.5-canary.9", "description": "A polyfill for non-dead, nomodule browsers.", "main": "dist/polyfill-nomodule.js", "license": "MIT", diff --git a/packages/next-swc/package.json b/packages/next-swc/package.json index 3b726b9e2479d..c611957d32637 100644 --- a/packages/next-swc/package.json +++ b/packages/next-swc/package.json @@ -1,6 +1,6 @@ { "name": "@next/swc", - "version": "13.5.5-canary.8", + "version": "13.5.5-canary.9", "private": true, "scripts": { "clean": "node ../../scripts/rm.mjs native", diff --git a/packages/next/package.json b/packages/next/package.json index 69a6a98f44715..a8e4b894dba1a 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "13.5.5-canary.8", + "version": "13.5.5-canary.9", "description": "The React Framework", "main": "./dist/server/next.js", "license": "MIT", @@ -90,7 +90,7 @@ ] }, "dependencies": { - "@next/env": "13.5.5-canary.8", + "@next/env": "13.5.5-canary.9", "@swc/helpers": "0.5.2", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001406", @@ -144,11 +144,11 @@ "@mswjs/interceptors": "0.23.0", "@napi-rs/cli": "2.16.2", "@napi-rs/triples": "1.1.0", - "@next/polyfill-module": "13.5.5-canary.8", - "@next/polyfill-nomodule": "13.5.5-canary.8", - "@next/react-dev-overlay": "13.5.5-canary.8", - "@next/react-refresh-utils": "13.5.5-canary.8", - "@next/swc": "13.5.5-canary.8", + "@next/polyfill-module": "13.5.5-canary.9", + "@next/polyfill-nomodule": "13.5.5-canary.9", + "@next/react-dev-overlay": "13.5.5-canary.9", + "@next/react-refresh-utils": "13.5.5-canary.9", + "@next/swc": "13.5.5-canary.9", "@opentelemetry/api": "1.4.1", "@playwright/test": "^1.35.1", "@taskr/clear": "1.1.0", diff --git a/packages/react-dev-overlay/package.json b/packages/react-dev-overlay/package.json index 1abaf0dfce948..7e5a509e21a8a 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": "13.5.5-canary.8", + "version": "13.5.5-canary.9", "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 146959ea4abdc..51cbe676eb643 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": "13.5.5-canary.8", + "version": "13.5.5-canary.9", "description": "An experimental package providing utilities for React Refresh.", "repository": { "url": "vercel/next.js", diff --git a/packages/third-parties/package.json b/packages/third-parties/package.json index f1ae6e97a4b7a..3786b4f46e3ff 100644 --- a/packages/third-parties/package.json +++ b/packages/third-parties/package.json @@ -1,6 +1,6 @@ { "name": "@next/third-parties", - "version": "13.5.5-canary.8", + "version": "13.5.5-canary.9", "private": true, "repository": { "url": "vercel/next.js", @@ -23,7 +23,7 @@ "third-party-capital": "1.0.20" }, "devDependencies": { - "next": "13.5.5-canary.8", + "next": "13.5.5-canary.9", "outdent": "0.8.0", "prettier": "2.5.1" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 53fa9069b9ea1..9c8344cfce5cb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -735,7 +735,7 @@ importers: packages/eslint-config-next: dependencies: '@next/eslint-plugin-next': - specifier: 13.5.5-canary.8 + specifier: 13.5.5-canary.9 version: link:../eslint-plugin-next '@rushstack/eslint-patch': specifier: ^1.3.3 @@ -796,7 +796,7 @@ importers: packages/next: dependencies: '@next/env': - specifier: 13.5.5-canary.8 + specifier: 13.5.5-canary.9 version: link:../next-env '@swc/helpers': specifier: 0.5.2 @@ -920,19 +920,19 @@ importers: specifier: 1.1.0 version: 1.1.0 '@next/polyfill-module': - specifier: 13.5.5-canary.8 + specifier: 13.5.5-canary.9 version: link:../next-polyfill-module '@next/polyfill-nomodule': - specifier: 13.5.5-canary.8 + specifier: 13.5.5-canary.9 version: link:../next-polyfill-nomodule '@next/react-dev-overlay': - specifier: 13.5.5-canary.8 + specifier: 13.5.5-canary.9 version: link:../react-dev-overlay '@next/react-refresh-utils': - specifier: 13.5.5-canary.8 + specifier: 13.5.5-canary.9 version: link:../react-refresh-utils '@next/swc': - specifier: 13.5.5-canary.8 + specifier: 13.5.5-canary.9 version: link:../next-swc '@opentelemetry/api': specifier: 1.4.1 @@ -1586,7 +1586,7 @@ importers: version: 1.0.20 devDependencies: next: - specifier: 13.5.5-canary.8 + specifier: 13.5.5-canary.9 version: link:../next outdent: specifier: 0.8.0 From 3da643a8b00f9ac2ee0b663b2865d06162173d38 Mon Sep 17 00:00:00 2001 From: Dima Voytenko Date: Thu, 12 Oct 2023 11:37:25 -0700 Subject: [PATCH 15/25] OpenTelemetry: ignore bubble errors to avoid spamming traces (#56625) The "bubble" errors are created here: https://github.com/vercel/next.js/blob/3f25a2e747fc27da6c2166e45d54fc95e96d7895/packages/next/src/server/next-server.ts#L1636-L1639 These errors do not appear to be true errors, but they tend to spam tracing. E.g. image --- packages/next/src/server/lib/trace/tracer.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/next/src/server/lib/trace/tracer.ts b/packages/next/src/server/lib/trace/tracer.ts index 60632b318afee..2183a2eff6c3e 100644 --- a/packages/next/src/server/lib/trace/tracer.ts +++ b/packages/next/src/server/lib/trace/tracer.ts @@ -34,11 +34,17 @@ const isPromise = (p: any): p is Promise => { return p !== null && typeof p === 'object' && typeof p.then === 'function' } +type BubbledError = Error & { bubble?: boolean } + const closeSpanWithError = (span: Span, error?: Error) => { - if (error) { - span.recordException(error) + if ((error as BubbledError | undefined)?.bubble === true) { + span.setAttribute('next.bubble', true) + } else { + if (error) { + span.recordException(error) + } + span.setStatus({ code: SpanStatusCode.ERROR, message: error?.message }) } - span.setStatus({ code: SpanStatusCode.ERROR, message: error?.message }) span.end() } From 230099b57f1a35a94d2ba6654ff0a4fdedddd4f6 Mon Sep 17 00:00:00 2001 From: Leah Date: Thu, 12 Oct 2023 21:17:01 +0200 Subject: [PATCH 16/25] fix(turbopack): always alias `server-only` and `client-only` (#56760) Closes WEB-1773 --- .../crates/next-core/src/next_import_map.rs | 56 ++++++++++++++++--- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/packages/next-swc/crates/next-core/src/next_import_map.rs b/packages/next-swc/crates/next-core/src/next_import_map.rs index 631270403889b..13e360f084719 100644 --- a/packages/next-swc/crates/next-core/src/next_import_map.rs +++ b/packages/next-swc/crates/next-core/src/next_import_map.rs @@ -1,6 +1,7 @@ use std::collections::{BTreeMap, HashMap}; use anyhow::{Context, Result}; +use indexmap::{indexmap, IndexMap}; use turbo_tasks::{Value, Vc}; use turbopack_binding::{ turbo::tasks_fs::{glob::Glob, FileSystem, FileSystemPath}, @@ -94,14 +95,7 @@ pub async fn get_next_client_import_map( } else { "" }; - import_map.insert_exact_alias( - "server-only", - request_to_import_mapping(app_dir, "next/dist/compiled/server-only"), - ); - import_map.insert_exact_alias( - "client-only", - request_to_import_mapping(app_dir, "next/dist/compiled/client-only"), - ); + import_map.insert_exact_alias( "react", request_to_import_mapping( @@ -154,6 +148,18 @@ pub async fn get_next_client_import_map( ClientContextType::Other => {} } + // see https://github.com/vercel/next.js/blob/8013ef7372fc545d49dbd060461224ceb563b454/packages/next/src/build/webpack-config.ts#L1449-L1531 + insert_exact_alias_map( + &mut import_map, + project_path, + indexmap! { + "server-only" => "next/dist/compiled/server-only/index".to_string(), + "client-only" => "next/dist/compiled/client-only/index".to_string(), + "next/dist/compiled/server-only" => "next/dist/compiled/server-only/index".to_string(), + "next/dist/compiled/client-only" => "next/dist/compiled/client-only/index".to_string(), + }, + ); + match ty.into_value() { ClientContextType::Pages { .. } | ClientContextType::App { .. } @@ -829,6 +835,30 @@ async fn insert_next_server_special_aliases( (_, ServerContextType::Middleware) => {} } + // see https://github.com/vercel/next.js/blob/8013ef7372fc545d49dbd060461224ceb563b454/packages/next/src/build/webpack-config.ts#L1449-L1531 + insert_exact_alias_map( + import_map, + project_path, + indexmap! { + "server-only" => "next/dist/compiled/server-only/empty".to_string(), + "client-only" => "next/dist/compiled/client-only/error".to_string(), + "next/dist/compiled/server-only" => "next/dist/compiled/server-only/empty".to_string(), + "next/dist/compiled/client-only" => "next/dist/compiled/client-only/error".to_string(), + }, + ); + + if ty == ServerContextType::Middleware { + insert_exact_alias_map( + import_map, + project_path, + indexmap! { + "client-only" => "next/dist/compiled/client-only/index".to_string(), + "next/dist/compiled/client-only" => "next/dist/compiled/client-only/index".to_string(), + "next/dist/compiled/client-only/error" => "next/dist/compiled/client-only/index".to_string(), + }, + ); + } + import_map.insert_exact_alias( "@vercel/og", external_if_node( @@ -1022,6 +1052,16 @@ fn export_value_to_import_mapping( } } +fn insert_exact_alias_map( + import_map: &mut ImportMap, + project_path: Vc, + map: IndexMap<&'static str, String>, +) { + for (pattern, request) in map { + import_map.insert_exact_alias(pattern, request_to_import_mapping(project_path, &request)); + } +} + /// Inserts an alias to an alternative of import mappings into an import map. fn insert_alias_to_alternatives<'a>( import_map: &mut ImportMap, From 0b5251c2f0a2e1529003566fad4335695be6759f Mon Sep 17 00:00:00 2001 From: Mayank Date: Fri, 13 Oct 2023 02:08:09 +0530 Subject: [PATCH 17/25] chore(example): bump `@radix-ui/react-icons` (#56452) Co-authored-by: Snyk bot <19733683+snyk-bot@users.noreply.github.com> --- examples/radix-ui/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/radix-ui/package.json b/examples/radix-ui/package.json index ea437a347265a..2fe64f2f71407 100644 --- a/examples/radix-ui/package.json +++ b/examples/radix-ui/package.json @@ -7,7 +7,7 @@ }, "dependencies": { "@radix-ui/react-dropdown-menu": "1.0.0", - "@radix-ui/react-icons": "1.1.1", + "@radix-ui/react-icons": "1.3.0", "next": "latest", "react": "latest", "react-dom": "latest" From 961fd01ebc098cfed124bf0822dcffe3eaa53373 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Thu, 12 Oct 2023 15:10:19 -0600 Subject: [PATCH 18/25] Utilize Promise.withResolvers (#56764) This utilizes `Promise.withResolvers` in a few places where it was done the old way. This also rearranges some imports and typings. --- .../lib/polyfill-promise-with-resolvers.ts | 6 +++- .../next/src/server/dev/next-dev-server.ts | 31 ++++++++++--------- .../default-route-matcher-manager.ts | 14 ++++----- packages/next/src/server/image-optimizer.ts | 13 -------- .../next/src/server/response-cache/web.ts | 13 +++----- 5 files changed, 34 insertions(+), 43 deletions(-) diff --git a/packages/next/src/lib/polyfill-promise-with-resolvers.ts b/packages/next/src/lib/polyfill-promise-with-resolvers.ts index 80144878eef2b..7400621f62934 100644 --- a/packages/next/src/lib/polyfill-promise-with-resolvers.ts +++ b/packages/next/src/lib/polyfill-promise-with-resolvers.ts @@ -9,7 +9,11 @@ if ( !('withResolvers' in Promise) || typeof Promise.withResolvers !== 'function' ) { - Promise.withResolvers = () => { + Promise.withResolvers = (): { + readonly promise: Promise + readonly resolve: (value: T | PromiseLike) => void + readonly reject: (reason: any) => void + } => { let resolvers: { resolve: (value: T | PromiseLike) => void reject: (reason: any) => void diff --git a/packages/next/src/server/dev/next-dev-server.ts b/packages/next/src/server/dev/next-dev-server.ts index 8c3896c2632f9..213d2fd934ccf 100644 --- a/packages/next/src/server/dev/next-dev-server.ts +++ b/packages/next/src/server/dev/next-dev-server.ts @@ -15,6 +15,11 @@ import type { NextUrlWithParsedQuery, } from '../request-meta' import type { DevBundlerService } from '../lib/dev-bundler-service' +import type { IncrementalCache } from '../lib/incremental-cache' +import type { UnwrapPromise } from '../../lib/coalesced-function' +import type { NodeNextResponse, NodeNextRequest } from '../base-http/node' +import type { RouteEnsurer } from '../future/route-matcher-managers/dev-route-matcher-manager' +import type { PagesManifest } from '../../build/webpack/plugins/pages-manifest-plugin' import fs from 'fs' import { Worker } from 'next/dist/compiled/jest-worker' @@ -39,26 +44,21 @@ import { setGlobal } from '../../trace' import { findPageFile } from '../lib/find-page-file' import { getNodeOptionsWithoutInspect } from '../lib/utils' import { withCoalescedInvoke } from '../../lib/coalesced-function' -import type { UnwrapPromise } from '../../lib/coalesced-function' import { loadDefaultErrorComponents } from '../load-default-error-components' import { DecodeError, MiddlewareNotFoundError } from '../../shared/lib/utils' import * as Log from '../../build/output/log' import isError, { getProperError } from '../../lib/is-error' -import type { NodeNextResponse, NodeNextRequest } from '../base-http/node' import { isMiddlewareFile } from '../../build/utils' import { formatServerError } from '../../lib/format-server-error' import { DevRouteMatcherManager } from '../future/route-matcher-managers/dev-route-matcher-manager' -import type { RouteEnsurer } from '../future/route-matcher-managers/dev-route-matcher-manager' import { DevPagesRouteMatcherProvider } from '../future/route-matcher-providers/dev/dev-pages-route-matcher-provider' import { DevPagesAPIRouteMatcherProvider } from '../future/route-matcher-providers/dev/dev-pages-api-route-matcher-provider' import { DevAppPageRouteMatcherProvider } from '../future/route-matcher-providers/dev/dev-app-page-route-matcher-provider' import { DevAppRouteRouteMatcherProvider } from '../future/route-matcher-providers/dev/dev-app-route-route-matcher-provider' -import type { PagesManifest } from '../../build/webpack/plugins/pages-manifest-plugin' import { NodeManifestLoader } from '../future/route-matcher-providers/helpers/manifest-loaders/node-manifest-loader' import { BatchedFileReader } from '../future/route-matcher-providers/dev/helpers/file-reader/batched-file-reader' import { DefaultFileReader } from '../future/route-matcher-providers/dev/helpers/file-reader/default-file-reader' import { NextBuildContext } from '../../build/build-context' -import type { IncrementalCache } from '../lib/incremental-cache' import LRUCache from 'next/dist/compiled/lru-cache' import { getMiddlewareRouteMatcher } from '../../shared/lib/router/utils/middleware-route-matcher' @@ -85,8 +85,11 @@ export interface Options extends ServerOptions { } export default class DevServer extends Server { - private devReady: Promise - private setDevReady?: Function + /** + * The promise that resolves when the server is ready. When this is unset + * the server is ready. + */ + private ready? = Promise.withResolvers() protected sortedRoutes?: string[] private pagesDir?: string private appDir?: string @@ -145,9 +148,6 @@ export default class DevServer extends Server { this.renderOpts.appDirDevErrorLogger = (err: any) => this.logErrorWithOriginalStack(err, 'app-dir') ;(this.renderOpts as any).ErrorDebug = ReactDevOverlay - this.devReady = new Promise((resolve) => { - this.setDevReady = resolve - }) this.staticPathsCache = new LRUCache({ // 5MB max: 5 * 1024 * 1024, @@ -268,7 +268,9 @@ export default class DevServer extends Server { await super.prepareImpl() await this.runInstrumentationHookIfAvailable() await this.matchers.reload() - this.setDevReady!() + + this.ready?.resolve() + this.ready = undefined // This is required by the tracing subsystem. setGlobal('appDir', this.appDir) @@ -428,7 +430,7 @@ export default class DevServer extends Server { res: BaseNextResponse, parsedUrl?: NextUrlWithParsedQuery ): Promise { - await this.devReady + await this.ready?.promise return await super.handleRequest(req, res, parsedUrl) } @@ -437,7 +439,7 @@ export default class DevServer extends Server { res: NodeNextResponse, parsedUrl: UrlWithParsedQuery ): Promise { - await this.devReady + await this.ready?.promise const { basePath } = this.nextConfig let originalPathname: string | null = null @@ -748,7 +750,8 @@ export default class DevServer extends Server { appPaths?: ReadonlyArray | null shouldEnsure: boolean }): Promise { - await this.devReady + await this.ready?.promise + const compilationErr = await this.getCompilationError(page) if (compilationErr) { // Wrap build errors so that they don't get logged again diff --git a/packages/next/src/server/future/route-matcher-managers/default-route-matcher-manager.ts b/packages/next/src/server/future/route-matcher-managers/default-route-matcher-manager.ts index df40fe02eacbe..fdae0fe3aa302 100644 --- a/packages/next/src/server/future/route-matcher-managers/default-route-matcher-manager.ts +++ b/packages/next/src/server/future/route-matcher-managers/default-route-matcher-manager.ts @@ -1,4 +1,6 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ +// This takes advantage of `Promise.withResolvers` which is polyfilled in +// this imported module. +import '../../../lib/polyfill-promise-with-resolvers' import { isDynamicRoute } from '../../../shared/lib/router/utils' import type { RouteKind } from '../route-kind' @@ -44,10 +46,8 @@ export class DefaultRouteMatcherManager implements RouteMatcherManager { private previousMatchers: ReadonlyArray = [] public async reload() { - let callbacks: { resolve: Function; reject: Function } - this.waitTillReadyPromise = new Promise((resolve, reject) => { - callbacks = { resolve, reject } - }) + const { promise, resolve, reject } = Promise.withResolvers() + this.waitTillReadyPromise = promise // Grab the compilation ID for this run, we'll verify it at the end to // ensure that if any routes were added before reloading is finished that @@ -182,11 +182,11 @@ export class DefaultRouteMatcherManager implements RouteMatcherManager { ) } } catch (err) { - callbacks!.reject(err) + reject(err) } finally { // The compilation ID matched, so mark the complication as finished. this.lastCompilationID = compilationID - callbacks!.resolve() + resolve() } } diff --git a/packages/next/src/server/image-optimizer.ts b/packages/next/src/server/image-optimizer.ts index 9f6e3b300572b..64d1baaa0c01c 100644 --- a/packages/next/src/server/image-optimizer.ts +++ b/packages/next/src/server/image-optimizer.ts @@ -794,16 +794,3 @@ export async function getImageSize( const { width, height } = imageSizeOf(buffer) return { width, height } } - -export class Deferred { - promise: Promise - resolve!: (value: T) => void - reject!: (error?: Error) => void - - constructor() { - this.promise = new Promise((resolve, reject) => { - this.resolve = resolve - this.reject = reject - }) - } -} diff --git a/packages/next/src/server/response-cache/web.ts b/packages/next/src/server/response-cache/web.ts index f255fdd5412d4..bab180e6a8a98 100644 --- a/packages/next/src/server/response-cache/web.ts +++ b/packages/next/src/server/response-cache/web.ts @@ -41,14 +41,11 @@ export default class WebResponseCache { return pendingResponse } - let resolver: (cacheEntry: ResponseCacheEntry | null) => void = () => {} - let rejecter: (error: Error) => void = () => {} - const promise: Promise = new Promise( - (resolve, reject) => { - resolver = resolve - rejecter = reject - } - ) + const { + promise, + resolve: resolver, + reject: rejecter, + } = Promise.withResolvers() if (pendingResponseKey) { this.pendingResponses.set(pendingResponseKey, promise) } From 476af246289d90c8f5672ffc3588bf64250331f3 Mon Sep 17 00:00:00 2001 From: Zack Tanner Date: Thu, 12 Oct 2023 14:38:44 -0700 Subject: [PATCH 19/25] Revert "Prefer module over main on main fields for app router server compiler" (#56766) This was causing some issues with our deployments. [slack x-ref](https://vercel.slack.com/archives/C04DUD7EB1B/p1697146531305779) --- packages/next/src/build/handle-externals.ts | 11 ++++- .../src/build/webpack-config-rules/resolve.ts | 40 ------------------- packages/next/src/build/webpack-config.ts | 27 ++++++++----- .../plugins/next-trace-entrypoints-plugin.ts | 1 + .../app-dir/app-external/app-external.test.ts | 38 +++++++++--------- .../react-server/3rd-party-package/page.js | 3 -- .../app/react-server/optout/page.js | 4 -- .../conditional-exports-optout/package.json | 3 -- .../conditional-exports-optout/react.js | 5 --- .../conditional-exports/package.json | 3 -- .../conditional-exports/react.js | 5 --- .../server-module-field/index.cjs | 1 - .../server-module-field/index.esm.js | 1 - .../server-module-field/package.json | 4 -- 14 files changed, 47 insertions(+), 99 deletions(-) delete mode 100644 packages/next/src/build/webpack-config-rules/resolve.ts delete mode 100644 test/e2e/app-dir/app-external/node_modules_bak/conditional-exports-optout/react.js delete mode 100644 test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/react.js delete mode 100644 test/e2e/app-dir/app-external/node_modules_bak/server-module-field/index.cjs delete mode 100644 test/e2e/app-dir/app-external/node_modules_bak/server-module-field/index.esm.js delete mode 100644 test/e2e/app-dir/app-external/node_modules_bak/server-module-field/package.json diff --git a/packages/next/src/build/handle-externals.ts b/packages/next/src/build/handle-externals.ts index 853ab2e3c68ab..2e0eb816b1495 100644 --- a/packages/next/src/build/handle-externals.ts +++ b/packages/next/src/build/handle-externals.ts @@ -44,6 +44,7 @@ export async function resolveExternal( context: string, request: string, isEsmRequested: boolean, + hasAppDir: boolean, getResolve: ( options: any ) => ( @@ -65,7 +66,11 @@ export async function resolveExternal( let preferEsmOptions = esmExternals && isEsmRequested ? [true, false] : [false] - + // Disable esm resolving for app/ and pages/ so for esm package using under pages/ + // won't load react through esm loader + if (hasAppDir) { + preferEsmOptions = [false] + } for (const preferEsm of preferEsmOptions) { const resolve = getResolve( preferEsm ? esmResolveOptions : nodeResolveOptions @@ -130,10 +135,12 @@ export function makeExternalHandler({ config, optOutBundlingPackageRegex, dir, + hasAppDir, }: { config: NextConfigComplete optOutBundlingPackageRegex: RegExp dir: string + hasAppDir: boolean }) { let resolvedExternalPackageDirs: Map const looseEsmExternals = config.experimental?.esmExternals === 'loose' @@ -286,6 +293,7 @@ export function makeExternalHandler({ context, request, isEsmRequested, + hasAppDir, getResolve, isLocal ? resolveNextExternal : undefined ) @@ -345,6 +353,7 @@ export function makeExternalHandler({ config.experimental.esmExternals, context, pkg + '/package.json', + hasAppDir, isEsmRequested, getResolve, isLocal ? resolveNextExternal : undefined diff --git a/packages/next/src/build/webpack-config-rules/resolve.ts b/packages/next/src/build/webpack-config-rules/resolve.ts deleted file mode 100644 index f50f6c92ee629..0000000000000 --- a/packages/next/src/build/webpack-config-rules/resolve.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { - COMPILER_NAMES, - type CompilerNameValues, -} from '../../shared/lib/constants' - -// exports. -export const edgeConditionNames = [ - 'edge-light', - 'worker', - // inherits the default conditions - '...', -] - -const mainFieldsPerCompiler: Record< - CompilerNameValues | 'app-router-server', - string[] -> = { - // For default case, prefer CJS over ESM on server side. e.g. pages dir SSR - [COMPILER_NAMES.server]: ['main', 'module'], - [COMPILER_NAMES.client]: ['browser', 'module', 'main'], - [COMPILER_NAMES.edgeServer]: edgeConditionNames, - // For app router since everything is bundled, prefer ESM over CJS - 'app-router-server': ['module', 'main'], -} - -export function getMainField( - pageType: 'app' | 'pages', - compilerType: CompilerNameValues -) { - if (compilerType === COMPILER_NAMES.edgeServer) { - return edgeConditionNames - } else if (compilerType === COMPILER_NAMES.client) { - return mainFieldsPerCompiler[COMPILER_NAMES.client] - } - - // Prefer module fields over main fields for isomorphic packages on server layer - return pageType === 'app' - ? mainFieldsPerCompiler['app-router-server'] - : mainFieldsPerCompiler[COMPILER_NAMES.server] -} diff --git a/packages/next/src/build/webpack-config.ts b/packages/next/src/build/webpack-config.ts index a20cf97a1e97f..1664d4377787c 100644 --- a/packages/next/src/build/webpack-config.ts +++ b/packages/next/src/build/webpack-config.ts @@ -74,10 +74,6 @@ import { needsExperimentalReact } from '../lib/needs-experimental-react' import { getDefineEnvPlugin } from './webpack/plugins/define-env-plugin' import type { SWCLoaderOptions } from './webpack/loaders/next-swc-loader' import { isResourceInPackages, makeExternalHandler } from './handle-externals' -import { - getMainField, - edgeConditionNames, -} from './webpack-config-rules/resolve' type ExcludesFalse = (x: T | false) => x is T type ClientEntries = { @@ -108,6 +104,21 @@ const babelIncludeRegexes: RegExp[] = [ const asyncStoragesRegex = /next[\\/]dist[\\/](esm[\\/])?client[\\/]components[\\/](static-generation-async-storage|action-async-storage|request-async-storage)/ +// exports. +const edgeConditionNames = [ + 'edge-light', + 'worker', + // inherits the default conditions + '...', +] + +// packageJson. +const mainFieldsPerCompiler: Record = { + [COMPILER_NAMES.server]: ['main', 'module'], + [COMPILER_NAMES.client]: ['browser', 'module', 'main'], + [COMPILER_NAMES.edgeServer]: edgeConditionNames, +} + // Support for NODE_PATH const nodePathList = (process.env.NODE_PATH || '') .split(process.platform === 'win32' ? ';' : ':') @@ -920,8 +931,7 @@ export default async function getBaseWebpackConfig( }, } : undefined), - // default main fields use pages dir ones, and customize app router ones in loaders. - mainFields: getMainField('pages', compilerType), + mainFields: mainFieldsPerCompiler[compilerType], ...(isEdgeServer && { conditionNames: edgeConditionNames, }), @@ -1029,6 +1039,7 @@ export default async function getBaseWebpackConfig( config, optOutBundlingPackageRegex, dir, + hasAppDir, }) const shouldIncludeExternalDirs = @@ -1599,7 +1610,6 @@ export default async function getBaseWebpackConfig( ], }, resolve: { - mainFields: getMainField('app', compilerType), conditionNames: reactServerCondition, // If missing the alias override here, the default alias will be used which aliases // react to the direct file path, not the package name. In that case the condition @@ -1744,9 +1754,6 @@ export default async function getBaseWebpackConfig( ], exclude: [codeCondition.exclude], use: swcLoaderForClientLayer, - resolve: { - mainFields: getMainField('app', compilerType), - }, }, ] : []), diff --git a/packages/next/src/build/webpack/plugins/next-trace-entrypoints-plugin.ts b/packages/next/src/build/webpack/plugins/next-trace-entrypoints-plugin.ts index 5ea193152a283..1f61d3520d29d 100644 --- a/packages/next/src/build/webpack/plugins/next-trace-entrypoints-plugin.ts +++ b/packages/next/src/build/webpack/plugins/next-trace-entrypoints-plugin.ts @@ -743,6 +743,7 @@ export class TraceEntryPointsPlugin implements webpack.WebpackPluginInstance { context, request, isEsmRequested, + !!this.appDirEnabled, (options) => (_: string, resRequest: string) => { return getResolve(options)(parent, resRequest, job) }, diff --git a/test/e2e/app-dir/app-external/app-external.test.ts b/test/e2e/app-dir/app-external/app-external.test.ts index b4e66cb205966..38592f5ba1b47 100644 --- a/test/e2e/app-dir/app-external/app-external.test.ts +++ b/test/e2e/app-dir/app-external/app-external.test.ts @@ -39,7 +39,7 @@ createNextDescribe( buildCommand: 'yarn build', skipDeployment: true, }, - ({ next }) => { + ({ next, isNextDev }) => { it('should be able to opt-out 3rd party packages being bundled in server components', async () => { await next.fetch('/react-server/optout').then(async (response) => { const result = await resolveStreamResponse(response) @@ -47,7 +47,6 @@ createNextDescribe( expect(result).toContain('Server subpath: subpath.default') expect(result).toContain('Client: index.default') expect(result).toContain('Client subpath: subpath.default') - expect(result).toContain('opt-out-react-version: 18.2.0') }) }) @@ -92,23 +91,24 @@ createNextDescribe( }) it('should resolve 3rd party package exports based on the react-server condition', async () => { - const $ = await next.render$('/react-server/3rd-party-package') - - const result = $('body').text() - - // Package should be resolved based on the react-server condition, - // as well as package's internal & external dependencies. - expect(result).toContain( - 'Server: index.react-server:react.subset:dep.server' - ) - expect(result).toContain('Client: index.default:react.full:dep.default') - - // Subpath exports should be resolved based on the condition too. - expect(result).toContain('Server subpath: subpath.react-server') - expect(result).toContain('Client subpath: subpath.default') - - // Prefer `module` field for isomorphic packages. - expect($('#main-field').text()).toContain('server-module-field:module') + await next + .fetch('/react-server/3rd-party-package') + .then(async (response) => { + const result = await resolveStreamResponse(response) + + // Package should be resolved based on the react-server condition, + // as well as package's internal & external dependencies. + expect(result).toContain( + 'Server: index.react-server:react.subset:dep.server' + ) + expect(result).toContain( + 'Client: index.default:react.full:dep.default' + ) + + // Subpath exports should be resolved based on the condition too. + expect(result).toContain('Server subpath: subpath.react-server') + expect(result).toContain('Client subpath: subpath.default') + }) }) it('should correctly collect global css imports and mark them as side effects', async () => { diff --git a/test/e2e/app-dir/app-external/app/react-server/3rd-party-package/page.js b/test/e2e/app-dir/app-external/app/react-server/3rd-party-package/page.js index 92e9f01672faa..33141e12f7685 100644 --- a/test/e2e/app-dir/app-external/app/react-server/3rd-party-package/page.js +++ b/test/e2e/app-dir/app-external/app/react-server/3rd-party-package/page.js @@ -1,6 +1,5 @@ import v from 'conditional-exports' import v1 from 'conditional-exports/subpath' -import { name as serverFieldName } from 'server-module-field' import Client from './client' @@ -12,8 +11,6 @@ export default function Page() { {`Server subpath: ${v1}`}
-
-
{`Server module field: ${serverFieldName}`}
) } diff --git a/test/e2e/app-dir/app-external/app/react-server/optout/page.js b/test/e2e/app-dir/app-external/app/react-server/optout/page.js index 45ba1ccff0358..fc7bd55ab86c3 100644 --- a/test/e2e/app-dir/app-external/app/react-server/optout/page.js +++ b/test/e2e/app-dir/app-external/app/react-server/optout/page.js @@ -1,6 +1,5 @@ import v from 'conditional-exports-optout' import v1 from 'conditional-exports-optout/subpath' -import { getReactVersion } from 'conditional-exports-optout/react' import Client from './client' @@ -12,9 +11,6 @@ export default function Page() { {`Server subpath: ${v1}`}
-

- {`opt-out-react-version: ${getReactVersion()}`} -

) } diff --git a/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports-optout/package.json b/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports-optout/package.json index 3355c20aad28a..fe1b70d109b2a 100644 --- a/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports-optout/package.json +++ b/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports-optout/package.json @@ -10,9 +10,6 @@ "react-server": "./subpath.server.js", "default": "./subpath.js" }, - "./react": { - "import": "./react.js" - }, "./package.json": "./package.json" } } diff --git a/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports-optout/react.js b/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports-optout/react.js deleted file mode 100644 index 4f2c2283ed693..0000000000000 --- a/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports-optout/react.js +++ /dev/null @@ -1,5 +0,0 @@ -import React from 'react' - -export function getReactVersion() { - return React.version -} diff --git a/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/package.json b/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/package.json index 06e09e177ae16..b51ade2e7acfe 100644 --- a/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/package.json +++ b/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/package.json @@ -16,9 +16,6 @@ "react-server": "./subpath.server.js", "default": "./subpath.js" }, - "./react": { - "import": "./react.js" - }, "./package.json": "./package.json" } } diff --git a/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/react.js b/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/react.js deleted file mode 100644 index 4f2c2283ed693..0000000000000 --- a/test/e2e/app-dir/app-external/node_modules_bak/conditional-exports/react.js +++ /dev/null @@ -1,5 +0,0 @@ -import React from 'react' - -export function getReactVersion() { - return React.version -} diff --git a/test/e2e/app-dir/app-external/node_modules_bak/server-module-field/index.cjs b/test/e2e/app-dir/app-external/node_modules_bak/server-module-field/index.cjs deleted file mode 100644 index bead07e159aa3..0000000000000 --- a/test/e2e/app-dir/app-external/node_modules_bak/server-module-field/index.cjs +++ /dev/null @@ -1 +0,0 @@ -exports.name = 'server-module-field:main' diff --git a/test/e2e/app-dir/app-external/node_modules_bak/server-module-field/index.esm.js b/test/e2e/app-dir/app-external/node_modules_bak/server-module-field/index.esm.js deleted file mode 100644 index 02218634f7d07..0000000000000 --- a/test/e2e/app-dir/app-external/node_modules_bak/server-module-field/index.esm.js +++ /dev/null @@ -1 +0,0 @@ -export const name = 'server-module-field:module' diff --git a/test/e2e/app-dir/app-external/node_modules_bak/server-module-field/package.json b/test/e2e/app-dir/app-external/node_modules_bak/server-module-field/package.json deleted file mode 100644 index d6cb0ed97cb3d..0000000000000 --- a/test/e2e/app-dir/app-external/node_modules_bak/server-module-field/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "main": "./index.cjs", - "module": "./index.esm.js" -} From 9288ef4921ac8e2abca5d4bd3c835dc13f7db7ad Mon Sep 17 00:00:00 2001 From: Hamir Mahal Date: Thu, 12 Oct 2023 14:55:14 -0700 Subject: [PATCH 20/25] feat: add self-documenting `.env.example` file (#56469) - fixes #56468 Co-authored-by: Steven <229881+styfle@users.noreply.github.com> --- packages/create-next-app/templates/app-tw/js/.env.example | 3 +++ packages/create-next-app/templates/app-tw/ts/.env.example | 3 +++ packages/create-next-app/templates/app/js/.env.example | 3 +++ packages/create-next-app/templates/app/ts/.env.example | 3 +++ packages/create-next-app/templates/default-tw/js/.env.example | 3 +++ packages/create-next-app/templates/default-tw/ts/.env.example | 3 +++ packages/create-next-app/templates/default/js/.env.example | 3 +++ packages/create-next-app/templates/default/ts/.env.example | 3 +++ 8 files changed, 24 insertions(+) create mode 100644 packages/create-next-app/templates/app-tw/js/.env.example create mode 100644 packages/create-next-app/templates/app-tw/ts/.env.example create mode 100644 packages/create-next-app/templates/app/js/.env.example create mode 100644 packages/create-next-app/templates/app/ts/.env.example create mode 100644 packages/create-next-app/templates/default-tw/js/.env.example create mode 100644 packages/create-next-app/templates/default-tw/ts/.env.example create mode 100644 packages/create-next-app/templates/default/js/.env.example create mode 100644 packages/create-next-app/templates/default/ts/.env.example diff --git a/packages/create-next-app/templates/app-tw/js/.env.example b/packages/create-next-app/templates/app-tw/js/.env.example new file mode 100644 index 0000000000000..ce586fad292cd --- /dev/null +++ b/packages/create-next-app/templates/app-tw/js/.env.example @@ -0,0 +1,3 @@ +# Rename this file to `.env.local` to use environment variables locally with `next dev` +# https://nextjs.org/docs/app/building-your-application/configuring/environment-variables +MY_HOST="example.com" diff --git a/packages/create-next-app/templates/app-tw/ts/.env.example b/packages/create-next-app/templates/app-tw/ts/.env.example new file mode 100644 index 0000000000000..ce586fad292cd --- /dev/null +++ b/packages/create-next-app/templates/app-tw/ts/.env.example @@ -0,0 +1,3 @@ +# Rename this file to `.env.local` to use environment variables locally with `next dev` +# https://nextjs.org/docs/app/building-your-application/configuring/environment-variables +MY_HOST="example.com" diff --git a/packages/create-next-app/templates/app/js/.env.example b/packages/create-next-app/templates/app/js/.env.example new file mode 100644 index 0000000000000..ce586fad292cd --- /dev/null +++ b/packages/create-next-app/templates/app/js/.env.example @@ -0,0 +1,3 @@ +# Rename this file to `.env.local` to use environment variables locally with `next dev` +# https://nextjs.org/docs/app/building-your-application/configuring/environment-variables +MY_HOST="example.com" diff --git a/packages/create-next-app/templates/app/ts/.env.example b/packages/create-next-app/templates/app/ts/.env.example new file mode 100644 index 0000000000000..ce586fad292cd --- /dev/null +++ b/packages/create-next-app/templates/app/ts/.env.example @@ -0,0 +1,3 @@ +# Rename this file to `.env.local` to use environment variables locally with `next dev` +# https://nextjs.org/docs/app/building-your-application/configuring/environment-variables +MY_HOST="example.com" diff --git a/packages/create-next-app/templates/default-tw/js/.env.example b/packages/create-next-app/templates/default-tw/js/.env.example new file mode 100644 index 0000000000000..7ac0a01551a65 --- /dev/null +++ b/packages/create-next-app/templates/default-tw/js/.env.example @@ -0,0 +1,3 @@ +# Rename this file to `.env.local` to use environment variables locally with `next dev` +# https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables +MY_HOST="example.com" diff --git a/packages/create-next-app/templates/default-tw/ts/.env.example b/packages/create-next-app/templates/default-tw/ts/.env.example new file mode 100644 index 0000000000000..7ac0a01551a65 --- /dev/null +++ b/packages/create-next-app/templates/default-tw/ts/.env.example @@ -0,0 +1,3 @@ +# Rename this file to `.env.local` to use environment variables locally with `next dev` +# https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables +MY_HOST="example.com" diff --git a/packages/create-next-app/templates/default/js/.env.example b/packages/create-next-app/templates/default/js/.env.example new file mode 100644 index 0000000000000..7ac0a01551a65 --- /dev/null +++ b/packages/create-next-app/templates/default/js/.env.example @@ -0,0 +1,3 @@ +# Rename this file to `.env.local` to use environment variables locally with `next dev` +# https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables +MY_HOST="example.com" diff --git a/packages/create-next-app/templates/default/ts/.env.example b/packages/create-next-app/templates/default/ts/.env.example new file mode 100644 index 0000000000000..7ac0a01551a65 --- /dev/null +++ b/packages/create-next-app/templates/default/ts/.env.example @@ -0,0 +1,3 @@ +# Rename this file to `.env.local` to use environment variables locally with `next dev` +# https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables +MY_HOST="example.com" From 786ef25e529e1fb2dda398aebd02ccbc8d0fb673 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Thu, 12 Oct 2023 16:20:50 -0600 Subject: [PATCH 21/25] Revalidate Type (#56763) This adds a new `Revalidate` type which is used internally by Next.js to associate the user inputted value of `revalidate` from `getStaticProps` or the exported `revalidate` variable in app directory. --- packages/next/src/build/index.ts | 3 +- packages/next/src/export/routes/app-page.ts | 2 +- packages/next/src/export/routes/pages.ts | 2 +- packages/next/src/export/types.ts | 5 ++-- packages/next/src/server/lib/revalidate.ts | 8 +++++ packages/next/src/server/render-result.ts | 4 ++- packages/next/src/server/render.tsx | 30 +++++++++++-------- .../next/src/server/response-cache/types.ts | 5 ++-- 8 files changed, 39 insertions(+), 20 deletions(-) create mode 100644 packages/next/src/server/lib/revalidate.ts diff --git a/packages/next/src/build/index.ts b/packages/next/src/build/index.ts index 580095c00d1a5..8236a4dd92747 100644 --- a/packages/next/src/build/index.ts +++ b/packages/next/src/build/index.ts @@ -9,6 +9,7 @@ import type { ExportAppWorker, ExportPageInput, } from '../export/types' +import type { Revalidate } from '../server/lib/revalidate' import '../lib/setup-exception-listeners' @@ -169,7 +170,7 @@ interface DataRouteRouteInfo { export interface SsgRoute extends ExperimentalBypassForInfo, DataRouteRouteInfo { - initialRevalidateSeconds: number | false + initialRevalidateSeconds: Revalidate srcRoute: string | null initialStatus?: number initialHeaders?: Record diff --git a/packages/next/src/export/routes/app-page.ts b/packages/next/src/export/routes/app-page.ts index b94b8fd26e417..c576fdf23886b 100644 --- a/packages/next/src/export/routes/app-page.ts +++ b/packages/next/src/export/routes/app-page.ts @@ -107,7 +107,7 @@ export async function exportAppPage( const html = result.toUnchunkedString() const { metadata } = result const flightData = metadata.pageData - const revalidate = metadata.revalidate + const revalidate = metadata.revalidate ?? false if (revalidate === 0) { if (isDynamicError) { diff --git a/packages/next/src/export/routes/pages.ts b/packages/next/src/export/routes/pages.ts index 31b1db6a3e401..20f542d22ece3 100644 --- a/packages/next/src/export/routes/pages.ts +++ b/packages/next/src/export/routes/pages.ts @@ -214,7 +214,7 @@ export async function exportPages( return { ampValidations, - revalidate: metadata.revalidate, + revalidate: metadata.revalidate ?? false, ssgNotFound, } } diff --git a/packages/next/src/export/types.ts b/packages/next/src/export/types.ts index d21405609ea43..071c17bfef247 100644 --- a/packages/next/src/export/types.ts +++ b/packages/next/src/export/types.ts @@ -7,6 +7,7 @@ import type AmpHtmlValidator from 'next/dist/compiled/amphtml-validator' import type { FontConfig } from '../server/font-utils' import type { ExportPathMap, NextConfigComplete } from '../server/config-shared' import type { Span } from '../trace' +import type { Revalidate } from '../server/lib/revalidate' export interface AmpValidation { page: string @@ -62,7 +63,7 @@ export type ExportedPageFile = { export type ExportRouteResult = | { ampValidations?: AmpValidation[] - revalidate: number | false + revalidate: Revalidate metadata?: { status?: number headers?: OutgoingHttpHeaders @@ -126,7 +127,7 @@ export type ExportAppResult = { /** * The revalidation time for the page in seconds. */ - revalidate?: number | false + revalidate?: Revalidate /** * The metadata for the page. */ diff --git a/packages/next/src/server/lib/revalidate.ts b/packages/next/src/server/lib/revalidate.ts new file mode 100644 index 0000000000000..2cb9fd60583a1 --- /dev/null +++ b/packages/next/src/server/lib/revalidate.ts @@ -0,0 +1,8 @@ +/** + * The revalidate option used internally for pages. A value of `false` means + * that the page should not be revalidated. A number means that the page + * should be revalidated after the given number of seconds (this also includes + * `1` which means to revalidate after 1 second). A value of `0` is not a valid + * value for this option. + */ +export type Revalidate = number | false diff --git a/packages/next/src/server/render-result.ts b/packages/next/src/server/render-result.ts index 0e8907c866c35..8a7b93653765f 100644 --- a/packages/next/src/server/render-result.ts +++ b/packages/next/src/server/render-result.ts @@ -1,12 +1,14 @@ import type { StaticGenerationStore } from '../client/components/static-generation-async-storage.external' +import type { Revalidate } from './lib/revalidate' import type { PipeTarget } from './pipe-readable' + import { pipeReadable } from './pipe-readable' type ContentTypeOption = string | undefined export type RenderResultMetadata = { pageData?: any - revalidate?: any + revalidate?: Revalidate staticBailoutInfo?: any assetQueryString?: string isNotFound?: boolean diff --git a/packages/next/src/server/render.tsx b/packages/next/src/server/render.tsx index d813406697942..fb17408808c98 100644 --- a/packages/next/src/server/render.tsx +++ b/packages/next/src/server/render.tsx @@ -37,6 +37,8 @@ import type { NextFontManifest } from '../build/webpack/plugins/next-font-manife import type { PagesModule } from './future/route-modules/pages/module' import type { ComponentsEnhancer } from '../shared/lib/utils' import type { NextParsedUrlQuery } from './request-meta' +import type { Revalidate } from './lib/revalidate' + import React from 'react' import ReactDOMServer from 'react-dom/server.browser' import { StyleRegistry, createStyleRegistry } from 'styled-jsx' @@ -820,7 +822,7 @@ export async function renderToHTMLImpl( } if (isSSG && !isFallback) { - let data: UnwrapPromise> + let data: Readonly>> try { data = await getTracer().trace( @@ -931,6 +933,7 @@ export async function renderToHTMLImpl( ) } + let revalidate: Revalidate if ('revalidate' in data) { if (data.revalidate && renderOpts.nextConfigOutput === 'export') { throw new Error( @@ -951,24 +954,28 @@ export async function renderToHTMLImpl( `\n\nTo never revalidate, you can set revalidate to \`false\` (only ran once at build-time).` + `\nTo revalidate as soon as possible, you can set the value to \`1\`.` ) - } else if (data.revalidate > 31536000) { - // if it's greater than a year for some reason error - console.warn( - `Warning: A page's revalidate option was set to more than a year for ${req.url}. This may have been done in error.` + - `\nTo only run getStaticProps at build-time and not revalidate at runtime, you can set \`revalidate\` to \`false\`!` - ) + } else { + if (data.revalidate > 31536000) { + // if it's greater than a year for some reason error + console.warn( + `Warning: A page's revalidate option was set to more than a year for ${req.url}. This may have been done in error.` + + `\nTo only run getStaticProps at build-time and not revalidate at runtime, you can set \`revalidate\` to \`false\`!` + ) + } + + revalidate = data.revalidate } } else if (data.revalidate === true) { // When enabled, revalidate after 1 second. This value is optimal for // the most up-to-date page possible, but without a 1-to-1 // request-refresh ratio. - data.revalidate = 1 + revalidate = 1 } else if ( data.revalidate === false || typeof data.revalidate === 'undefined' ) { // By default, we never revalidate. - data.revalidate = false + revalidate = false } else { throw new Error( `A page's revalidate option must be seconds expressed as a natural number. Mixed numbers and strings cannot be used. Received '${JSON.stringify( @@ -978,7 +985,7 @@ export async function renderToHTMLImpl( } } else { // By default, we never revalidate. - ;(data as any).revalidate = false + revalidate = false } props.pageProps = Object.assign( @@ -988,8 +995,7 @@ export async function renderToHTMLImpl( ) // pass up revalidate and props for export - renderResultMeta.revalidate = - 'revalidate' in data ? data.revalidate : undefined + renderResultMeta.revalidate = revalidate renderResultMeta.pageData = props // this must come after revalidate is added to renderResultMeta diff --git a/packages/next/src/server/response-cache/types.ts b/packages/next/src/server/response-cache/types.ts index 93015b6282505..e1af17df729e5 100644 --- a/packages/next/src/server/response-cache/types.ts +++ b/packages/next/src/server/response-cache/types.ts @@ -1,5 +1,6 @@ import type { OutgoingHttpHeaders } from 'http' import type RenderResult from '../render-result' +import type { Revalidate } from '../lib/revalidate' export interface ResponseCacheBase { get( @@ -93,7 +94,7 @@ export type ResponseCacheValue = | CachedRouteValue export type ResponseCacheEntry = { - revalidate?: number | false + revalidate?: Revalidate value: ResponseCacheValue | null isStale?: boolean | -1 isMiss?: boolean @@ -121,6 +122,6 @@ export interface IncrementalCache { set: ( key: string, data: IncrementalCacheValue | null, - ctx: { revalidate: number | false } + ctx: { revalidate: Revalidate } ) => Promise } From 10ba5f772b6ec31b651ac6f964bc8cada457cd22 Mon Sep 17 00:00:00 2001 From: Zack Tanner Date: Thu, 12 Oct 2023 16:03:48 -0700 Subject: [PATCH 22/25] Revert static worker refactor (#56767) The changes to this worker from #55841 seem to also cause strange behavior where the process doesn't exit despite sending an exit signal. Reverting until we can spend the time to investigate what the issue is. [slack x-ref](https://vercel.slack.com/archives/C03S8ED1DKM/p1697129702263269) [slack x-ref](https://vercel.slack.com/archives/C056QDZARTM/p1697149427099799?thread_ts=1696351087.736439&cid=C056QDZARTM) --- packages/next/src/build/index.ts | 26 ++--- packages/next/src/export/index.ts | 46 ++++----- packages/next/src/lib/worker.ts | 159 ++++++++++-------------------- 3 files changed, 83 insertions(+), 148 deletions(-) diff --git a/packages/next/src/build/index.ts b/packages/next/src/build/index.ts index 8236a4dd92747..3eca074f8a65b 100644 --- a/packages/next/src/build/index.ts +++ b/packages/next/src/build/index.ts @@ -4,11 +4,7 @@ import type { PagesManifest } from './webpack/plugins/pages-manifest-plugin' import type { ExportPathMap, NextConfigComplete } from '../server/config-shared' import type { MiddlewareManifest } from './webpack/plugins/middleware-plugin' import type { ActionManifest } from './webpack/plugins/flight-client-entry-plugin' -import type { - ExportAppOptions, - ExportAppWorker, - ExportPageInput, -} from '../export/types' +import type { ExportAppOptions, ExportAppWorker } from '../export/types' import type { Revalidate } from '../server/lib/revalidate' import '../lib/setup-exception-listeners' @@ -1209,16 +1205,7 @@ export default async function build( ) { let infoPrinted = false - return Worker.create< - Pick< - typeof import('./worker'), - | 'hasCustomGetInitialProps' - | 'isPageStatic' - | 'getDefinedNamedExports' - | 'exportPage' - >, - [ExportPageInput] - >(staticWorkerPath, { + return new Worker(staticWorkerPath, { timeout: timeout * 1000, onRestart: (method, [arg], attempts) => { if (method === 'exportPage') { @@ -1265,7 +1252,14 @@ export default async function build( 'getDefinedNamedExports', 'exportPage', ], - }) + }) as Worker & + Pick< + typeof import('./worker'), + | 'hasCustomGetInitialProps' + | 'isPageStatic' + | 'getDefinedNamedExports' + | 'exportPage' + > } let CacheHandler: any diff --git a/packages/next/src/export/index.ts b/packages/next/src/export/index.ts index 25a51a6163163..32a71d7a6c2cc 100644 --- a/packages/next/src/export/index.ts +++ b/packages/next/src/export/index.ts @@ -3,7 +3,6 @@ import type { ExportAppOptions, ExportWorker, WorkerRenderOptsPartial, - ExportPageInput, } from './types' import type { PrerenderManifest } from '../build' import type { PagesManifest } from '../build/webpack/plugins/pages-manifest-plugin' @@ -174,32 +173,29 @@ function setupWorkers( let infoPrinted = false - const worker = Worker.create( - require.resolve('./worker'), - { - timeout: timeout * 1000, - onRestart: (_method, [{ path }], attempts) => { - if (attempts >= 3) { - throw new ExportError( - `Static page generation for ${path} is still timing out after 3 attempts. See more info here https://nextjs.org/docs/messages/static-page-generation-timeout` - ) - } + const worker = new Worker(require.resolve('./worker'), { + timeout: timeout * 1000, + onRestart: (_method, [{ path }], attempts) => { + if (attempts >= 3) { + throw new ExportError( + `Static page generation for ${path} is still timing out after 3 attempts. See more info here https://nextjs.org/docs/messages/static-page-generation-timeout` + ) + } + Log.warn( + `Restarted static page generation for ${path} because it took more than ${timeout} seconds` + ) + if (!infoPrinted) { Log.warn( - `Restarted static page generation for ${path} because it took more than ${timeout} seconds` + 'See more info here https://nextjs.org/docs/messages/static-page-generation-timeout' ) - if (!infoPrinted) { - Log.warn( - 'See more info here https://nextjs.org/docs/messages/static-page-generation-timeout' - ) - infoPrinted = true - } - }, - maxRetries: 0, - numWorkers: threads, - enableWorkerThreads: nextConfig.experimental.workerThreads, - exposedMethods: ['default'], - } - ) + infoPrinted = true + } + }, + maxRetries: 0, + numWorkers: threads, + enableWorkerThreads: nextConfig.experimental.workerThreads, + exposedMethods: ['default'], + }) as Worker & typeof import('./worker') return { pages: worker.default, diff --git a/packages/next/src/lib/worker.ts b/packages/next/src/lib/worker.ts index 5cc0af1a18aaf..152a2f50f01f1 100644 --- a/packages/next/src/lib/worker.ts +++ b/packages/next/src/lib/worker.ts @@ -1,10 +1,6 @@ import type { ChildProcess } from 'child_process' import { Worker as JestWorker } from 'next/dist/compiled/jest-worker' import { getNodeOptionsWithoutInspect } from '../server/lib/utils' - -// We need this as we're using `Promise.withResolvers` which is not available in the node typings -import '../lib/polyfill-promise-with-resolvers' - type FarmOptions = ConstructorParameters[1] const RESTARTED = Symbol('restarted') @@ -17,58 +13,45 @@ const cleanupWorkers = (worker: JestWorker) => { } } -type Options< - T extends object = object, - Args extends any[] = any[] -> = FarmOptions & { - timeout?: number - onRestart?: (method: string, args: Args, attempts: number) => void - exposedMethods: ReadonlyArray - enableWorkerThreads?: boolean -} - -export class Worker { - private _worker?: JestWorker +export class Worker { + private _worker: JestWorker | undefined - /** - * Creates a new worker with the correct typings associated with the selected - * methods. - */ - public static create( + constructor( workerPath: string, - options: Options - ): Worker & T { - return new Worker(workerPath, options) as Worker & T - } - - constructor(workerPath: string, options: Options) { + options: FarmOptions & { + timeout?: number + onRestart?: (method: string, args: any[], attempts: number) => void + exposedMethods: ReadonlyArray + enableWorkerThreads?: boolean + } + ) { let { timeout, onRestart, ...farmOptions } = options let restartPromise: Promise let resolveRestartPromise: (arg: typeof RESTARTED) => void let activeTasks = 0 + this._worker = undefined + const createWorker = () => { - const worker = new JestWorker(workerPath, { + this._worker = new JestWorker(workerPath, { ...farmOptions, forkOptions: { ...farmOptions.forkOptions, env: { - ...farmOptions.forkOptions?.env, + ...((farmOptions.forkOptions?.env || {}) as any), ...process.env, - // We don't pass down NODE_OPTIONS as it can lead to extra memory - // usage, + // we don't pass down NODE_OPTIONS as it can + // extra memory usage NODE_OPTIONS: getNodeOptionsWithoutInspect() .replace(/--max-old-space-size=[\d]{1,}/, '') .trim(), - }, - stdio: 'inherit', + } as any, }, - }) - - const { promise, resolve } = Promise.withResolvers() - restartPromise = promise - resolveRestartPromise = resolve + }) as JestWorker + restartPromise = new Promise( + (resolve) => (resolveRestartPromise = resolve) + ) /** * Jest Worker has two worker types, ChildProcessWorker (uses child_process) and NodeThreadWorker (uses worker_threads) @@ -80,14 +63,11 @@ export class Worker { * But this property is not available in NodeThreadWorker, so we need to check if we are using ChildProcessWorker */ if (!farmOptions.enableWorkerThreads) { - const poolWorkers: { _child?: ChildProcess }[] = - // @ts-expect-error - we're accessing a private property - worker._workerPool?._workers ?? [] - - for (const poolWorker of poolWorkers) { - if (!poolWorker._child) continue - - poolWorker._child.once('exit', (code, signal) => { + for (const worker of ((this._worker as any)._workerPool?._workers || + []) as { + _child?: ChildProcess + }[]) { + worker._child?.on('exit', (code, signal) => { // log unexpected exit if .end() wasn't called if ((code || (signal && signal !== 'SIGINT')) && this._worker) { console.error( @@ -98,22 +78,16 @@ export class Worker { } } - return worker + this._worker.getStdout().pipe(process.stdout) + this._worker.getStderr().pipe(process.stderr) } - - // Create the first worker. - this._worker = createWorker() + createWorker() const onHanging = () => { const worker = this._worker if (!worker) return - - // Grab the current restart promise, and create a new worker. const resolve = resolveRestartPromise - this._worker = createWorker() - - // Once the old worker is ended, resolve the restart promise to signal to - // any active tasks that the worker had to be restarted. + createWorker() worker.end().then(() => { resolve(RESTARTED) }) @@ -122,62 +96,33 @@ export class Worker { let hangingTimer: NodeJS.Timeout | false = false const onActivity = () => { - // If there was an active hanging timer, clear it. if (hangingTimer) clearTimeout(hangingTimer) - - // If there are no active tasks, we don't need to start a new hanging - // timer. - if (activeTasks === 0) return - - hangingTimer = setTimeout(onHanging, timeout) + hangingTimer = activeTasks > 0 && setTimeout(onHanging, timeout) } - const wrapMethodWithTimeout = - (methodName: keyof T) => - async (...args: Args) => { - activeTasks++ - - try { - let attempts = 0 - for (;;) { - // Mark that we're doing work, we want to ensure that if the worker - // halts for any reason, we restart it. - onActivity() - - const result = await Promise.race([ - // Either we'll get the result from the worker, or we'll get the - // restart promise to fire. - // @ts-expect-error - we're grabbing a dynamic method on the worker - this._worker[methodName](...args), - restartPromise, - ]) - - // If the result anything besides `RESTARTED`, we can return it, as - // it's the actual result from the worker. - if (result !== RESTARTED) { - return result + for (const method of farmOptions.exposedMethods) { + if (method.startsWith('_')) continue + ;(this as any)[method] = timeout + ? // eslint-disable-next-line no-loop-func + async (...args: any[]) => { + activeTasks++ + try { + let attempts = 0 + for (;;) { + onActivity() + const result = await Promise.race([ + (this._worker as any)[method](...args), + restartPromise, + ]) + if (result !== RESTARTED) return result + if (onRestart) onRestart(method, args, ++attempts) + } + } finally { + activeTasks-- + onActivity() } - - // Otherwise, we'll need to restart the worker, and try again. - if (onRestart) onRestart(methodName.toString(), args, ++attempts) } - } finally { - activeTasks-- - onActivity() - } - } - - for (const name of farmOptions.exposedMethods) { - if (name.startsWith('_')) continue - - // @ts-expect-error - we're grabbing a dynamic method on the worker - let method = this._worker[name].bind(this._worker) - if (timeout) { - method = wrapMethodWithTimeout(name) - } - - // @ts-expect-error - we're dynamically creating methods - this[name] = method + : (this._worker as any)[method].bind(this._worker) } } From f306108b37b79baf20269fa89d53f492976254c5 Mon Sep 17 00:00:00 2001 From: vercel-release-bot Date: Thu, 12 Oct 2023 23:09:37 +0000 Subject: [PATCH 23/25] v13.5.5-canary.10 --- lerna.json | 2 +- packages/create-next-app/package.json | 2 +- packages/eslint-config-next/package.json | 4 ++-- packages/eslint-plugin-next/package.json | 2 +- packages/font/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-storybook/package.json | 2 +- packages/next-polyfill-module/package.json | 2 +- packages/next-polyfill-nomodule/package.json | 2 +- packages/next-swc/package.json | 2 +- packages/next/package.json | 14 +++++++------- packages/react-dev-overlay/package.json | 2 +- packages/react-refresh-utils/package.json | 2 +- packages/third-parties/package.json | 4 ++-- pnpm-lock.yaml | 16 ++++++++-------- 18 files changed, 33 insertions(+), 33 deletions(-) diff --git a/lerna.json b/lerna.json index 82212d1d74eb0..a4dc7769b068e 100644 --- a/lerna.json +++ b/lerna.json @@ -16,5 +16,5 @@ "registry": "https://registry.npmjs.org/" } }, - "version": "13.5.5-canary.9" + "version": "13.5.5-canary.10" } diff --git a/packages/create-next-app/package.json b/packages/create-next-app/package.json index 2e662421fe8fe..5f5cb358e41ec 100644 --- a/packages/create-next-app/package.json +++ b/packages/create-next-app/package.json @@ -1,6 +1,6 @@ { "name": "create-next-app", - "version": "13.5.5-canary.9", + "version": "13.5.5-canary.10", "keywords": [ "react", "next", diff --git a/packages/eslint-config-next/package.json b/packages/eslint-config-next/package.json index 5e917b536b47c..2d99c4d1cad3b 100644 --- a/packages/eslint-config-next/package.json +++ b/packages/eslint-config-next/package.json @@ -1,6 +1,6 @@ { "name": "eslint-config-next", - "version": "13.5.5-canary.9", + "version": "13.5.5-canary.10", "description": "ESLint configuration used by Next.js.", "main": "index.js", "license": "MIT", @@ -10,7 +10,7 @@ }, "homepage": "https://nextjs.org/docs/app/building-your-application/configuring/eslint#eslint-config", "dependencies": { - "@next/eslint-plugin-next": "13.5.5-canary.9", + "@next/eslint-plugin-next": "13.5.5-canary.10", "@rushstack/eslint-patch": "^1.3.3", "@typescript-eslint/parser": "^5.4.2 || ^6.0.0", "eslint-import-resolver-node": "^0.3.6", diff --git a/packages/eslint-plugin-next/package.json b/packages/eslint-plugin-next/package.json index 7da03da6fabfa..10e7b0ee53bcf 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": "13.5.5-canary.9", + "version": "13.5.5-canary.10", "description": "ESLint plugin for Next.js.", "main": "dist/index.js", "license": "MIT", diff --git a/packages/font/package.json b/packages/font/package.json index 8e08e7804bae2..7cf1e049ca04b 100644 --- a/packages/font/package.json +++ b/packages/font/package.json @@ -1,6 +1,6 @@ { "name": "@next/font", - "version": "13.5.5-canary.9", + "version": "13.5.5-canary.10", "repository": { "url": "vercel/next.js", "directory": "packages/font" diff --git a/packages/next-bundle-analyzer/package.json b/packages/next-bundle-analyzer/package.json index 08366e689174e..4324526a3ea41 100644 --- a/packages/next-bundle-analyzer/package.json +++ b/packages/next-bundle-analyzer/package.json @@ -1,6 +1,6 @@ { "name": "@next/bundle-analyzer", - "version": "13.5.5-canary.9", + "version": "13.5.5-canary.10", "main": "index.js", "types": "index.d.ts", "license": "MIT", diff --git a/packages/next-codemod/package.json b/packages/next-codemod/package.json index 9951d49e949f5..3630d974b2e05 100644 --- a/packages/next-codemod/package.json +++ b/packages/next-codemod/package.json @@ -1,6 +1,6 @@ { "name": "@next/codemod", - "version": "13.5.5-canary.9", + "version": "13.5.5-canary.10", "license": "MIT", "repository": { "type": "git", diff --git a/packages/next-env/package.json b/packages/next-env/package.json index 651022ad8b73e..2f9f3d2c29137 100644 --- a/packages/next-env/package.json +++ b/packages/next-env/package.json @@ -1,6 +1,6 @@ { "name": "@next/env", - "version": "13.5.5-canary.9", + "version": "13.5.5-canary.10", "keywords": [ "react", "next", diff --git a/packages/next-mdx/package.json b/packages/next-mdx/package.json index b0bfd040cd3f1..e0422e8127e16 100644 --- a/packages/next-mdx/package.json +++ b/packages/next-mdx/package.json @@ -1,6 +1,6 @@ { "name": "@next/mdx", - "version": "13.5.5-canary.9", + "version": "13.5.5-canary.10", "main": "index.js", "license": "MIT", "repository": { diff --git a/packages/next-plugin-storybook/package.json b/packages/next-plugin-storybook/package.json index db4c4a63240ea..f9e5bae7e7957 100644 --- a/packages/next-plugin-storybook/package.json +++ b/packages/next-plugin-storybook/package.json @@ -1,6 +1,6 @@ { "name": "@next/plugin-storybook", - "version": "13.5.5-canary.9", + "version": "13.5.5-canary.10", "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 148fc7900d410..7f95bfa69f9bc 100644 --- a/packages/next-polyfill-module/package.json +++ b/packages/next-polyfill-module/package.json @@ -1,6 +1,6 @@ { "name": "@next/polyfill-module", - "version": "13.5.5-canary.9", + "version": "13.5.5-canary.10", "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 4277cc48f6a7d..c4cc8ad446d5a 100644 --- a/packages/next-polyfill-nomodule/package.json +++ b/packages/next-polyfill-nomodule/package.json @@ -1,6 +1,6 @@ { "name": "@next/polyfill-nomodule", - "version": "13.5.5-canary.9", + "version": "13.5.5-canary.10", "description": "A polyfill for non-dead, nomodule browsers.", "main": "dist/polyfill-nomodule.js", "license": "MIT", diff --git a/packages/next-swc/package.json b/packages/next-swc/package.json index c611957d32637..bd994e41c220a 100644 --- a/packages/next-swc/package.json +++ b/packages/next-swc/package.json @@ -1,6 +1,6 @@ { "name": "@next/swc", - "version": "13.5.5-canary.9", + "version": "13.5.5-canary.10", "private": true, "scripts": { "clean": "node ../../scripts/rm.mjs native", diff --git a/packages/next/package.json b/packages/next/package.json index a8e4b894dba1a..72b8c595f3ef3 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "13.5.5-canary.9", + "version": "13.5.5-canary.10", "description": "The React Framework", "main": "./dist/server/next.js", "license": "MIT", @@ -90,7 +90,7 @@ ] }, "dependencies": { - "@next/env": "13.5.5-canary.9", + "@next/env": "13.5.5-canary.10", "@swc/helpers": "0.5.2", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001406", @@ -144,11 +144,11 @@ "@mswjs/interceptors": "0.23.0", "@napi-rs/cli": "2.16.2", "@napi-rs/triples": "1.1.0", - "@next/polyfill-module": "13.5.5-canary.9", - "@next/polyfill-nomodule": "13.5.5-canary.9", - "@next/react-dev-overlay": "13.5.5-canary.9", - "@next/react-refresh-utils": "13.5.5-canary.9", - "@next/swc": "13.5.5-canary.9", + "@next/polyfill-module": "13.5.5-canary.10", + "@next/polyfill-nomodule": "13.5.5-canary.10", + "@next/react-dev-overlay": "13.5.5-canary.10", + "@next/react-refresh-utils": "13.5.5-canary.10", + "@next/swc": "13.5.5-canary.10", "@opentelemetry/api": "1.4.1", "@playwright/test": "^1.35.1", "@taskr/clear": "1.1.0", diff --git a/packages/react-dev-overlay/package.json b/packages/react-dev-overlay/package.json index 7e5a509e21a8a..5b1ff91233d84 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": "13.5.5-canary.9", + "version": "13.5.5-canary.10", "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 51cbe676eb643..8d1852f934060 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": "13.5.5-canary.9", + "version": "13.5.5-canary.10", "description": "An experimental package providing utilities for React Refresh.", "repository": { "url": "vercel/next.js", diff --git a/packages/third-parties/package.json b/packages/third-parties/package.json index 3786b4f46e3ff..74470f077fc2a 100644 --- a/packages/third-parties/package.json +++ b/packages/third-parties/package.json @@ -1,6 +1,6 @@ { "name": "@next/third-parties", - "version": "13.5.5-canary.9", + "version": "13.5.5-canary.10", "private": true, "repository": { "url": "vercel/next.js", @@ -23,7 +23,7 @@ "third-party-capital": "1.0.20" }, "devDependencies": { - "next": "13.5.5-canary.9", + "next": "13.5.5-canary.10", "outdent": "0.8.0", "prettier": "2.5.1" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9c8344cfce5cb..8b0d3918c6af2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -735,7 +735,7 @@ importers: packages/eslint-config-next: dependencies: '@next/eslint-plugin-next': - specifier: 13.5.5-canary.9 + specifier: 13.5.5-canary.10 version: link:../eslint-plugin-next '@rushstack/eslint-patch': specifier: ^1.3.3 @@ -796,7 +796,7 @@ importers: packages/next: dependencies: '@next/env': - specifier: 13.5.5-canary.9 + specifier: 13.5.5-canary.10 version: link:../next-env '@swc/helpers': specifier: 0.5.2 @@ -920,19 +920,19 @@ importers: specifier: 1.1.0 version: 1.1.0 '@next/polyfill-module': - specifier: 13.5.5-canary.9 + specifier: 13.5.5-canary.10 version: link:../next-polyfill-module '@next/polyfill-nomodule': - specifier: 13.5.5-canary.9 + specifier: 13.5.5-canary.10 version: link:../next-polyfill-nomodule '@next/react-dev-overlay': - specifier: 13.5.5-canary.9 + specifier: 13.5.5-canary.10 version: link:../react-dev-overlay '@next/react-refresh-utils': - specifier: 13.5.5-canary.9 + specifier: 13.5.5-canary.10 version: link:../react-refresh-utils '@next/swc': - specifier: 13.5.5-canary.9 + specifier: 13.5.5-canary.10 version: link:../next-swc '@opentelemetry/api': specifier: 1.4.1 @@ -1586,7 +1586,7 @@ importers: version: 1.0.20 devDependencies: next: - specifier: 13.5.5-canary.9 + specifier: 13.5.5-canary.10 version: link:../next outdent: specifier: 0.8.0 From fd2724ace0d6a64e5e8d25b0762f4f341b5ffab9 Mon Sep 17 00:00:00 2001 From: Michael Novotny Date: Thu, 12 Oct 2023 18:18:22 -0500 Subject: [PATCH 24/25] Changes codeblock filename delimiter (#56712) Based on feedback from #56603, the `/` can be interpreted as file paths instead of filename separators / delimiters. We'll change them to use pipes `|` instead. --- .../01-fetching-caching-and-revalidating.mdx | 6 +-- .../06-optimizing/04-metadata.mdx | 4 +- .../01-metadata/app-icons.mdx | 8 +-- .../01-metadata/opengraph-image.mdx | 12 ++--- .../route-segment-config.mdx | 32 +++++------ .../04-functions/generate-metadata.mdx | 54 +++++++++---------- 6 files changed, 58 insertions(+), 58 deletions(-) diff --git a/docs/02-app/01-building-your-application/02-data-fetching/01-fetching-caching-and-revalidating.mdx b/docs/02-app/01-building-your-application/02-data-fetching/01-fetching-caching-and-revalidating.mdx index f73228c63590a..3c28cd1ac0ad9 100644 --- a/docs/02-app/01-building-your-application/02-data-fetching/01-fetching-caching-and-revalidating.mdx +++ b/docs/02-app/01-building-your-application/02-data-fetching/01-fetching-caching-and-revalidating.mdx @@ -107,7 +107,7 @@ fetch('https://...', { next: { revalidate: 3600 } }) Alternatively, to revalidate all `fetch` requests in a route segment, you can use the [Segment Config Options](/docs/app/api-reference/file-conventions/route-segment-config). -```jsx filename="layout.js / page.js" +```jsx filename="layout.js | page.js" export const revalidate = 3600 // revalidate at most every hour ``` @@ -250,7 +250,7 @@ If an error is thrown while attempting to revalidate data, the last successfully To opt out of caching for individual `fetch` requests, you can set the `cache` option in `fetch` to `'no-store'`. This will fetch data dynamically, on every request. -```js filename="layout.js / page.js" +```js filename="layout.js | page.js" fetch('https://...', { cache: 'no-store' }) ``` @@ -262,7 +262,7 @@ If you have multiple `fetch` requests in a route segment (e.g. a Layout or Page) For example, using `const dynamic = 'force-dynamic'` will cause all data to be fetched at request time, and the segment to be rendered dynamically. -```js filename="layout.js / page.js" +```js filename="layout.js | page.js" // Add export const dynamic = 'force-dynamic' ``` diff --git a/docs/02-app/01-building-your-application/06-optimizing/04-metadata.mdx b/docs/02-app/01-building-your-application/06-optimizing/04-metadata.mdx index 77996a627a27f..deb9f0e9233bd 100644 --- a/docs/02-app/01-building-your-application/06-optimizing/04-metadata.mdx +++ b/docs/02-app/01-building-your-application/06-optimizing/04-metadata.mdx @@ -21,7 +21,7 @@ With both these options, Next.js will automatically generate the relevant ` ``` -```jsx filename="layout.js / page.js" +```jsx filename="layout.js | page.js" export const metadata = { openGraph: { title: 'Next.js', @@ -571,7 +571,7 @@ export const metadata: Metadata = { > **Good to know**: We recommend using the [file-based Metadata API](/docs/app/api-reference/file-conventions/metadata/app-icons#image-files-ico-jpg-png) for icons where possible. Rather than having to sync the config export with actual files, the file-based API will automatically generate the correct metadata for you. -```jsx filename="layout.js / page.js" +```jsx filename="layout.js | page.js" export const metadata = { icons: { icon: '/icon.png', @@ -595,7 +595,7 @@ export const metadata = { /> ``` -```jsx filename="layout.js / page.js" +```jsx filename="layout.js | page.js" export const metadata = { icons: { icon: [{ url: '/icon.png' }, new URL('/icon.png', 'https://example.com')], @@ -639,7 +639,7 @@ Learn more about [theme-color](https://developer.mozilla.org/docs/Web/HTML/Eleme **Simple theme color** -```jsx filename="layout.js / page.js" +```jsx filename="layout.js | page.js" export const metadata = { themeColor: 'black', } @@ -651,7 +651,7 @@ export const metadata = { **With media attribute** -```jsx filename="layout.js / page.js" +```jsx filename="layout.js | page.js" export const metadata = { themeColor: [ { media: '(prefers-color-scheme: light)', color: 'cyan' }, @@ -669,7 +669,7 @@ export const metadata = { A web application manifest, as defined in the [Web Application Manifest specification](https://developer.mozilla.org/docs/Web/Manifest). -```jsx filename="layout.js / page.js" +```jsx filename="layout.js | page.js" export const metadata = { manifest: 'https://nextjs.org/manifest.json', } @@ -683,7 +683,7 @@ export const metadata = { Learn more about the [Twitter Card markup reference](https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/markup). -```jsx filename="layout.js / page.js" +```jsx filename="layout.js | page.js" export const metadata = { twitter: { card: 'summary_large_image', @@ -707,7 +707,7 @@ export const metadata = { ``` -```jsx filename="layout.js / page.js" +```jsx filename="layout.js | page.js" export const metadata = { twitter: { card: 'app', @@ -759,7 +759,7 @@ export const metadata = { > **Good to know**: The `viewport` meta tag is automatically set with the following default values. Usually, manual configuration is unnecessary as the default is sufficient. However, the information is provided for completeness. -```jsx filename="layout.js / page.js" +```jsx filename="layout.js | page.js" export const metadata = { viewport: { width: 'device-width', @@ -778,7 +778,7 @@ export const metadata = { ### `verification` -```jsx filename="layout.js / page.js" +```jsx filename="layout.js | page.js" export const metadata = { verification: { google: 'google', @@ -801,7 +801,7 @@ export const metadata = { ### `appleWebApp` -```jsx filename="layout.js / page.js" +```jsx filename="layout.js | page.js" export const metadata = { itunes: { appId: 'myAppStoreID', @@ -845,7 +845,7 @@ export const metadata = { ### `alternates` -```jsx filename="layout.js / page.js" +```jsx filename="layout.js | page.js" export const metadata = { alternates: { canonical: 'https://nextjs.org', @@ -881,7 +881,7 @@ export const metadata = { ### `appLinks` -```jsx filename="layout.js / page.js" +```jsx filename="layout.js | page.js" export const metadata = { appLinks: { ios: { @@ -913,7 +913,7 @@ export const metadata = { Describes a collection of records, documents, or other materials of historical interest ([source](https://www.w3.org/TR/2011/WD-html5-20110113/links.html#rel-archives)). -```jsx filename="layout.js / page.js" +```jsx filename="layout.js | page.js" export const metadata = { archives: ['https://nextjs.org/13'], } @@ -925,7 +925,7 @@ export const metadata = { ### `assets` -```jsx filename="layout.js / page.js" +```jsx filename="layout.js | page.js" export const metadata = { assets: ['https://nextjs.org/assets'], } @@ -937,7 +937,7 @@ export const metadata = { ### `bookmarks` -```jsx filename="layout.js / page.js" +```jsx filename="layout.js | page.js" export const metadata = { bookmarks: ['https://nextjs.org/13'], } @@ -949,7 +949,7 @@ export const metadata = { ### `category` -```jsx filename="layout.js / page.js" +```jsx filename="layout.js | page.js" export const metadata = { category: 'technology', } @@ -963,7 +963,7 @@ export const metadata = { All metadata options should be covered using the built-in support. However, there may be custom metadata tags specific to your site, or brand new metadata tags just released. You can use the `other` option to render any custom metadata tag. -```jsx filename="layout.js / page.js" +```jsx filename="layout.js | page.js" export const metadata = { other: { custom: 'meta', From e0cd06531bcd004fe73c1ab8836c28584c5c8286 Mon Sep 17 00:00:00 2001 From: vercel-release-bot Date: Thu, 12 Oct 2023 23:23:04 +0000 Subject: [PATCH 25/25] v13.5.5-canary.11 --- lerna.json | 2 +- packages/create-next-app/package.json | 2 +- packages/eslint-config-next/package.json | 4 ++-- packages/eslint-plugin-next/package.json | 2 +- packages/font/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-storybook/package.json | 2 +- packages/next-polyfill-module/package.json | 2 +- packages/next-polyfill-nomodule/package.json | 2 +- packages/next-swc/package.json | 2 +- packages/next/package.json | 14 +++++++------- packages/react-dev-overlay/package.json | 2 +- packages/react-refresh-utils/package.json | 2 +- packages/third-parties/package.json | 4 ++-- pnpm-lock.yaml | 16 ++++++++-------- 18 files changed, 33 insertions(+), 33 deletions(-) diff --git a/lerna.json b/lerna.json index a4dc7769b068e..e71150afa9fe6 100644 --- a/lerna.json +++ b/lerna.json @@ -16,5 +16,5 @@ "registry": "https://registry.npmjs.org/" } }, - "version": "13.5.5-canary.10" + "version": "13.5.5-canary.11" } diff --git a/packages/create-next-app/package.json b/packages/create-next-app/package.json index 5f5cb358e41ec..6bd6103250d4f 100644 --- a/packages/create-next-app/package.json +++ b/packages/create-next-app/package.json @@ -1,6 +1,6 @@ { "name": "create-next-app", - "version": "13.5.5-canary.10", + "version": "13.5.5-canary.11", "keywords": [ "react", "next", diff --git a/packages/eslint-config-next/package.json b/packages/eslint-config-next/package.json index 2d99c4d1cad3b..b41d5193f8c9b 100644 --- a/packages/eslint-config-next/package.json +++ b/packages/eslint-config-next/package.json @@ -1,6 +1,6 @@ { "name": "eslint-config-next", - "version": "13.5.5-canary.10", + "version": "13.5.5-canary.11", "description": "ESLint configuration used by Next.js.", "main": "index.js", "license": "MIT", @@ -10,7 +10,7 @@ }, "homepage": "https://nextjs.org/docs/app/building-your-application/configuring/eslint#eslint-config", "dependencies": { - "@next/eslint-plugin-next": "13.5.5-canary.10", + "@next/eslint-plugin-next": "13.5.5-canary.11", "@rushstack/eslint-patch": "^1.3.3", "@typescript-eslint/parser": "^5.4.2 || ^6.0.0", "eslint-import-resolver-node": "^0.3.6", diff --git a/packages/eslint-plugin-next/package.json b/packages/eslint-plugin-next/package.json index 10e7b0ee53bcf..01fdcd3a0d053 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": "13.5.5-canary.10", + "version": "13.5.5-canary.11", "description": "ESLint plugin for Next.js.", "main": "dist/index.js", "license": "MIT", diff --git a/packages/font/package.json b/packages/font/package.json index 7cf1e049ca04b..daf05dee73c4b 100644 --- a/packages/font/package.json +++ b/packages/font/package.json @@ -1,6 +1,6 @@ { "name": "@next/font", - "version": "13.5.5-canary.10", + "version": "13.5.5-canary.11", "repository": { "url": "vercel/next.js", "directory": "packages/font" diff --git a/packages/next-bundle-analyzer/package.json b/packages/next-bundle-analyzer/package.json index 4324526a3ea41..f14ada397ee83 100644 --- a/packages/next-bundle-analyzer/package.json +++ b/packages/next-bundle-analyzer/package.json @@ -1,6 +1,6 @@ { "name": "@next/bundle-analyzer", - "version": "13.5.5-canary.10", + "version": "13.5.5-canary.11", "main": "index.js", "types": "index.d.ts", "license": "MIT", diff --git a/packages/next-codemod/package.json b/packages/next-codemod/package.json index 3630d974b2e05..fe2c588218724 100644 --- a/packages/next-codemod/package.json +++ b/packages/next-codemod/package.json @@ -1,6 +1,6 @@ { "name": "@next/codemod", - "version": "13.5.5-canary.10", + "version": "13.5.5-canary.11", "license": "MIT", "repository": { "type": "git", diff --git a/packages/next-env/package.json b/packages/next-env/package.json index 2f9f3d2c29137..07a35d1589b87 100644 --- a/packages/next-env/package.json +++ b/packages/next-env/package.json @@ -1,6 +1,6 @@ { "name": "@next/env", - "version": "13.5.5-canary.10", + "version": "13.5.5-canary.11", "keywords": [ "react", "next", diff --git a/packages/next-mdx/package.json b/packages/next-mdx/package.json index e0422e8127e16..3b47892f0ca4a 100644 --- a/packages/next-mdx/package.json +++ b/packages/next-mdx/package.json @@ -1,6 +1,6 @@ { "name": "@next/mdx", - "version": "13.5.5-canary.10", + "version": "13.5.5-canary.11", "main": "index.js", "license": "MIT", "repository": { diff --git a/packages/next-plugin-storybook/package.json b/packages/next-plugin-storybook/package.json index f9e5bae7e7957..6bdb0347f0221 100644 --- a/packages/next-plugin-storybook/package.json +++ b/packages/next-plugin-storybook/package.json @@ -1,6 +1,6 @@ { "name": "@next/plugin-storybook", - "version": "13.5.5-canary.10", + "version": "13.5.5-canary.11", "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 7f95bfa69f9bc..7ba60af11194b 100644 --- a/packages/next-polyfill-module/package.json +++ b/packages/next-polyfill-module/package.json @@ -1,6 +1,6 @@ { "name": "@next/polyfill-module", - "version": "13.5.5-canary.10", + "version": "13.5.5-canary.11", "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 c4cc8ad446d5a..b08b4d8394be3 100644 --- a/packages/next-polyfill-nomodule/package.json +++ b/packages/next-polyfill-nomodule/package.json @@ -1,6 +1,6 @@ { "name": "@next/polyfill-nomodule", - "version": "13.5.5-canary.10", + "version": "13.5.5-canary.11", "description": "A polyfill for non-dead, nomodule browsers.", "main": "dist/polyfill-nomodule.js", "license": "MIT", diff --git a/packages/next-swc/package.json b/packages/next-swc/package.json index bd994e41c220a..2c28720169298 100644 --- a/packages/next-swc/package.json +++ b/packages/next-swc/package.json @@ -1,6 +1,6 @@ { "name": "@next/swc", - "version": "13.5.5-canary.10", + "version": "13.5.5-canary.11", "private": true, "scripts": { "clean": "node ../../scripts/rm.mjs native", diff --git a/packages/next/package.json b/packages/next/package.json index 72b8c595f3ef3..658ac474cecab 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "13.5.5-canary.10", + "version": "13.5.5-canary.11", "description": "The React Framework", "main": "./dist/server/next.js", "license": "MIT", @@ -90,7 +90,7 @@ ] }, "dependencies": { - "@next/env": "13.5.5-canary.10", + "@next/env": "13.5.5-canary.11", "@swc/helpers": "0.5.2", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001406", @@ -144,11 +144,11 @@ "@mswjs/interceptors": "0.23.0", "@napi-rs/cli": "2.16.2", "@napi-rs/triples": "1.1.0", - "@next/polyfill-module": "13.5.5-canary.10", - "@next/polyfill-nomodule": "13.5.5-canary.10", - "@next/react-dev-overlay": "13.5.5-canary.10", - "@next/react-refresh-utils": "13.5.5-canary.10", - "@next/swc": "13.5.5-canary.10", + "@next/polyfill-module": "13.5.5-canary.11", + "@next/polyfill-nomodule": "13.5.5-canary.11", + "@next/react-dev-overlay": "13.5.5-canary.11", + "@next/react-refresh-utils": "13.5.5-canary.11", + "@next/swc": "13.5.5-canary.11", "@opentelemetry/api": "1.4.1", "@playwright/test": "^1.35.1", "@taskr/clear": "1.1.0", diff --git a/packages/react-dev-overlay/package.json b/packages/react-dev-overlay/package.json index 5b1ff91233d84..5fae8eaacde57 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": "13.5.5-canary.10", + "version": "13.5.5-canary.11", "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 8d1852f934060..e335ed564599f 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": "13.5.5-canary.10", + "version": "13.5.5-canary.11", "description": "An experimental package providing utilities for React Refresh.", "repository": { "url": "vercel/next.js", diff --git a/packages/third-parties/package.json b/packages/third-parties/package.json index 74470f077fc2a..38b4a9b0964f5 100644 --- a/packages/third-parties/package.json +++ b/packages/third-parties/package.json @@ -1,6 +1,6 @@ { "name": "@next/third-parties", - "version": "13.5.5-canary.10", + "version": "13.5.5-canary.11", "private": true, "repository": { "url": "vercel/next.js", @@ -23,7 +23,7 @@ "third-party-capital": "1.0.20" }, "devDependencies": { - "next": "13.5.5-canary.10", + "next": "13.5.5-canary.11", "outdent": "0.8.0", "prettier": "2.5.1" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8b0d3918c6af2..2bd236397921c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -735,7 +735,7 @@ importers: packages/eslint-config-next: dependencies: '@next/eslint-plugin-next': - specifier: 13.5.5-canary.10 + specifier: 13.5.5-canary.11 version: link:../eslint-plugin-next '@rushstack/eslint-patch': specifier: ^1.3.3 @@ -796,7 +796,7 @@ importers: packages/next: dependencies: '@next/env': - specifier: 13.5.5-canary.10 + specifier: 13.5.5-canary.11 version: link:../next-env '@swc/helpers': specifier: 0.5.2 @@ -920,19 +920,19 @@ importers: specifier: 1.1.0 version: 1.1.0 '@next/polyfill-module': - specifier: 13.5.5-canary.10 + specifier: 13.5.5-canary.11 version: link:../next-polyfill-module '@next/polyfill-nomodule': - specifier: 13.5.5-canary.10 + specifier: 13.5.5-canary.11 version: link:../next-polyfill-nomodule '@next/react-dev-overlay': - specifier: 13.5.5-canary.10 + specifier: 13.5.5-canary.11 version: link:../react-dev-overlay '@next/react-refresh-utils': - specifier: 13.5.5-canary.10 + specifier: 13.5.5-canary.11 version: link:../react-refresh-utils '@next/swc': - specifier: 13.5.5-canary.10 + specifier: 13.5.5-canary.11 version: link:../next-swc '@opentelemetry/api': specifier: 1.4.1 @@ -1586,7 +1586,7 @@ importers: version: 1.0.20 devDependencies: next: - specifier: 13.5.5-canary.10 + specifier: 13.5.5-canary.11 version: link:../next outdent: specifier: 0.8.0