From 6aae39c759362f3f1689072b5b261a7d2b2a66a5 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Wed, 14 Dec 2022 19:52:52 +0100 Subject: [PATCH] Fix app client entry key for windows (#44011) ## Bug The app client entry key was in win32 slashes like `app\blog`, and when we add the new layer checking logic in #43197, `name.startsWith('app/')` doesn't work. Fixes #43854 Fixes #43902 image - [x] Related issues linked using `fixes #number` - [x] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) --- azure-pipelines.yml | 41 +++++++++++++++++-- package.json | 1 + packages/create-next-app/package.json | 1 - packages/font/package.json | 2 +- .../plugins/flight-client-entry-plugin.ts | 5 ++- packages/react-dev-overlay/package.json | 2 +- packages/react-refresh-utils/package.json | 2 +- pnpm-lock.yaml | 9 ++-- .../app-dir-basic/app/blog/page.js | 3 ++ test/integration/app-dir-basic/app/layout.js | 8 ++++ test/integration/app-dir-basic/app/page.js | 3 ++ test/integration/app-dir-basic/next.config.js | 5 +++ .../app-dir-basic/test/index.test.js | 33 +++++++++++++++ 13 files changed, 103 insertions(+), 12 deletions(-) create mode 100644 test/integration/app-dir-basic/app/blog/page.js create mode 100644 test/integration/app-dir-basic/app/layout.js create mode 100644 test/integration/app-dir-basic/app/page.js create mode 100644 test/integration/app-dir-basic/next.config.js create mode 100644 test/integration/app-dir-basic/test/index.test.js diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 4ca6149a8a4a791..00377d09a11d1c0 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -35,7 +35,8 @@ variables: PNPM_CACHE_FOLDER: $(Pipeline.Workspace)/.pnpm-store PNPM_VERSION: 7.3.0 NEXT_TELEMETRY_DISABLED: '1' - node_version: ^14.19.0 + node_14_version: ^14.19.0 + node_16_version: ^16.8.0 stages: - stage: Test @@ -46,7 +47,7 @@ stages: steps: - task: NodeTool@0 inputs: - versionSpec: $(node_version) + versionSpec: $(node_14_version) displayName: 'Install Node.js' - bash: | @@ -84,7 +85,7 @@ stages: - task: NodeTool@0 inputs: - versionSpec: $(node_version) + versionSpec: $(node_14_version) displayName: 'Install Node.js' - bash: | @@ -107,3 +108,37 @@ stages: - script: node run-tests.js --type unit condition: eq(variables['isDocsOnly'], 'No') displayName: 'Run tests' + + - job: test_integration_app_dir + pool: + vmImage: 'windows-2019' + steps: + - task: NodeTool@0 + inputs: + versionSpec: $(node_16_version) + displayName: 'Install Node.js' + + - bash: | + node scripts/run-for-change.js --not --type docs --exec echo "##vso[task.setvariable variable=isDocsOnly]No" + displayName: 'Check Docs Only Change' + + - script: npm i -g pnpm@$(PNPM_VERSION) + condition: eq(variables['isDocsOnly'], 'No') + + - script: pnpm config set store-dir $(PNPM_CACHE_FOLDER) + condition: eq(variables['isDocsOnly'], 'No') + + - script: pnpm store path + condition: eq(variables['isDocsOnly'], 'No') + + - script: pnpm install && pnpm run build + condition: eq(variables['isDocsOnly'], 'No') + displayName: 'Install and build' + + - script: npx playwright install chromium + condition: eq(variables['isDocsOnly'], 'No') + + - script: | + node run-tests.js -c 1 test/integration/app-dir-basic/test/index.test.js + condition: eq(variables['isDocsOnly'], 'No') + displayName: 'Run tests' diff --git a/package.json b/package.json index 77b2d103f9f78b5..690163865715ff2 100644 --- a/package.json +++ b/package.json @@ -198,6 +198,7 @@ "release": "6.3.1", "request-promise-core": "1.1.2", "resolve-from": "5.0.0", + "rimraf": "3.0.2", "sass": "1.54.0", "seedrandom": "3.0.5", "selenium-webdriver": "4.0.0-beta.4", diff --git a/packages/create-next-app/package.json b/packages/create-next-app/package.json index 1527f63482b474e..468e92677fd4386 100644 --- a/packages/create-next-app/package.json +++ b/packages/create-next-app/package.json @@ -45,7 +45,6 @@ "cross-spawn": "6.0.5", "got": "10.7.0", "prompts": "2.1.0", - "rimraf": "3.0.2", "tar": "4.4.10", "update-check": "1.5.4", "validate-npm-package-name": "3.0.0" diff --git a/packages/font/package.json b/packages/font/package.json index 52f2e95ec396835..ef6a0f145d84429 100644 --- a/packages/font/package.json +++ b/packages/font/package.json @@ -12,7 +12,7 @@ ], "license": "MIT", "scripts": { - "build": "rm -rf dist && pnpm ncc-fontkit && tsc -d -p tsconfig.json", + "build": "rimraf dist && pnpm ncc-fontkit && tsc -d -p tsconfig.json", "prepublishOnly": "cd ../../ && turbo run build", "dev": "pnpm ncc-fontkit && tsc -d -w -p tsconfig.json", "typescript": "tsec --noEmit -p tsconfig.json", diff --git a/packages/next/build/webpack/plugins/flight-client-entry-plugin.ts b/packages/next/build/webpack/plugins/flight-client-entry-plugin.ts index 57e2ff6ee13a3dd..93a055bd1cf5dec 100644 --- a/packages/next/build/webpack/plugins/flight-client-entry-plugin.ts +++ b/packages/next/build/webpack/plugins/flight-client-entry-plugin.ts @@ -509,7 +509,10 @@ export class FlightClientEntryPlugin { // Add for the client compilation // Inject the entry to the client compiler. if (this.dev) { - const pageKey = COMPILER_NAMES.client + bundlePath + const pageKey = (COMPILER_NAMES.client + bundlePath).replace( + /\\/g, + path.posix.sep + ) if (!entries[pageKey]) { entries[pageKey] = { type: EntryTypes.CHILD_ENTRY, diff --git a/packages/react-dev-overlay/package.json b/packages/react-dev-overlay/package.json index 8a39adb18544e6b..917eb33e11974ed 100644 --- a/packages/react-dev-overlay/package.json +++ b/packages/react-dev-overlay/package.json @@ -12,7 +12,7 @@ "author": "Joe Haddad ", "license": "MIT", "scripts": { - "build": "rm -rf dist && tsc -d -p tsconfig.json", + "build": "rimraf dist && tsc -d -p tsconfig.json", "prepublishOnly": "cd ../../ && turbo run build", "dev": "tsc -d -w -p tsconfig.json", "typescript": "tsec --noEmit -p tsconfig.json" diff --git a/packages/react-refresh-utils/package.json b/packages/react-refresh-utils/package.json index 3778d55c68b357b..4c4329d018df971 100644 --- a/packages/react-refresh-utils/package.json +++ b/packages/react-refresh-utils/package.json @@ -12,7 +12,7 @@ "author": "Joe Haddad ", "license": "MIT", "scripts": { - "build": "rm -rf dist && tsc -d -p tsconfig.json", + "build": "rimraf dist && tsc -d -p tsconfig.json", "prepublishOnly": "cd ../../ && turbo run build", "dev": "tsc -d -w -p tsconfig.json" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2101ea16dbc7a3d..e9d12e0058f4992 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -163,6 +163,7 @@ importers: release: 6.3.1 request-promise-core: 1.1.2 resolve-from: 5.0.0 + rimraf: 3.0.2 sass: 1.54.0 seedrandom: 3.0.5 selenium-webdriver: 4.0.0-beta.4 @@ -337,6 +338,7 @@ importers: release: 6.3.1 request-promise-core: 1.1.2_request@2.88.2 resolve-from: 5.0.0 + rimraf: 3.0.2 sass: 1.54.0 seedrandom: 3.0.5 selenium-webdriver: 4.0.0-beta.4 @@ -403,7 +405,6 @@ importers: cross-spawn: 6.0.5 got: 10.7.0 prompts: 2.1.0 - rimraf: 3.0.2 tar: 4.4.10 update-check: 1.5.4 validate-npm-package-name: 3.0.0 @@ -425,7 +426,6 @@ importers: cross-spawn: 6.0.5 got: 10.7.0 prompts: 2.1.0 - rimraf: 3.0.2 tar: 4.4.10 update-check: 1.5.4 validate-npm-package-name: 3.0.0 @@ -9805,7 +9805,7 @@ packages: dev: true /concat-map/0.0.1: - resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} /concat-stream/1.6.2: resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} @@ -14291,6 +14291,7 @@ packages: /is-docker/2.0.0: resolution: {integrity: sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ==} engines: {node: '>=8'} + dev: true /is-docker/2.2.1: resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} @@ -14642,7 +14643,7 @@ packages: resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} engines: {node: '>=8'} dependencies: - is-docker: 2.0.0 + is-docker: 2.2.1 /is-yarn-global/0.3.0: resolution: {integrity: sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==} diff --git a/test/integration/app-dir-basic/app/blog/page.js b/test/integration/app-dir-basic/app/blog/page.js new file mode 100644 index 000000000000000..f8a7b0ab425271f --- /dev/null +++ b/test/integration/app-dir-basic/app/blog/page.js @@ -0,0 +1,3 @@ +export default function page() { + return <>blog +} diff --git a/test/integration/app-dir-basic/app/layout.js b/test/integration/app-dir-basic/app/layout.js new file mode 100644 index 000000000000000..747270b45987a2b --- /dev/null +++ b/test/integration/app-dir-basic/app/layout.js @@ -0,0 +1,8 @@ +export default function RootLayout({ children }) { + return ( + + + {children} + + ) +} diff --git a/test/integration/app-dir-basic/app/page.js b/test/integration/app-dir-basic/app/page.js new file mode 100644 index 000000000000000..8c790ee258cfb0c --- /dev/null +++ b/test/integration/app-dir-basic/app/page.js @@ -0,0 +1,3 @@ +export default function page() { + return <>page +} diff --git a/test/integration/app-dir-basic/next.config.js b/test/integration/app-dir-basic/next.config.js new file mode 100644 index 000000000000000..cfa3ac3d7aa94b3 --- /dev/null +++ b/test/integration/app-dir-basic/next.config.js @@ -0,0 +1,5 @@ +module.exports = { + experimental: { + appDir: true, + }, +} diff --git a/test/integration/app-dir-basic/test/index.test.js b/test/integration/app-dir-basic/test/index.test.js new file mode 100644 index 000000000000000..4dd430ba144cfd6 --- /dev/null +++ b/test/integration/app-dir-basic/test/index.test.js @@ -0,0 +1,33 @@ +/* eslint-env jest */ + +import { join } from 'path' +import { runDevSuite, runProdSuite, renderViaHTTP } from 'next-test-utils' + +import webdriver from 'next-webdriver' +const appDir = join(__dirname, '..') + +function runTests(context, env) { + describe('App Dir Basic', () => { + it('should render html properly', async () => { + const indexHtml = await renderViaHTTP(context.appPort, '/') + const blogHtml = await renderViaHTTP(context.appPort, '/blog') + + expect(indexHtml).toContain('page') + expect(blogHtml).toContain('blog') + }) + + it('should hydrate pages properly', async () => { + const browser = await webdriver(context.appPort, '/') + const indexHtml = await browser.waitForElementByCss('body').text() + const url = await browser.url() + await browser.loadPage(url + 'blog') + const blogHtml = await browser.waitForElementByCss('body').text() + + expect(indexHtml).toContain('page') + expect(blogHtml).toContain('blog') + }) + }) +} + +runDevSuite('App Dir Basic', appDir, { runTests }) +runProdSuite('App Dir Basic', appDir, { runTests })