From b6fd25d6837d21be2f712a36ab274e120bc0bb7b Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Wed, 25 Oct 2023 13:50:33 -0700 Subject: [PATCH 1/3] Apply react-server transform and valication to middleware --- packages/next/src/build/webpack-config.ts | 8 ++++---- packages/next/src/lib/constants.ts | 5 +---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/next/src/build/webpack-config.ts b/packages/next/src/build/webpack-config.ts index f9c462c1bdc8b..b180e71fd1865 100644 --- a/packages/next/src/build/webpack-config.ts +++ b/packages/next/src/build/webpack-config.ts @@ -461,8 +461,8 @@ export default async function getBaseWebpackConfig( const swcLoaderForMiddlewareLayer = useSWCLoader ? getSwcLoader({ - serverComponents: false, - isReactServerLayer: false, + serverComponents: true, + isReactServerLayer: true, }) : // When using Babel, we will have to use SWC to do the optimization // for middleware to tree shake the unused default optimized imports like "next/server". @@ -470,8 +470,8 @@ export default async function getBaseWebpackConfig( // acceptable as Babel will not be recommended. [ getSwcLoader({ - serverComponents: false, - isReactServerLayer: false, + serverComponents: true, + isReactServerLayer: true, }), getBabelLoader(), ] diff --git a/packages/next/src/lib/constants.ts b/packages/next/src/lib/constants.ts index 25d026a4a43c9..b943c19cecdf1 100644 --- a/packages/next/src/lib/constants.ts +++ b/packages/next/src/lib/constants.ts @@ -154,12 +154,9 @@ const WEBPACK_LAYERS = { WEBPACK_LAYERS_NAMES.actionBrowser, WEBPACK_LAYERS_NAMES.appMetadataRoute, WEBPACK_LAYERS_NAMES.appRouteHandler, - ], - nonClientServerTarget: [ - // plus middleware and pages api WEBPACK_LAYERS_NAMES.middleware, - WEBPACK_LAYERS_NAMES.api, ], + nonClientServerTarget: [WEBPACK_LAYERS_NAMES.api], app: [ WEBPACK_LAYERS_NAMES.reactServerComponents, WEBPACK_LAYERS_NAMES.actionBrowser, From 0c979e9feac63f273b20d172681e4ee13f31c9b7 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Wed, 25 Oct 2023 15:06:03 -0700 Subject: [PATCH 2/3] new test --- test/e2e/module-layer/index.test.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/test/e2e/module-layer/index.test.ts b/test/e2e/module-layer/index.test.ts index 4aef0e35246fe..26389eac72d27 100644 --- a/test/e2e/module-layer/index.test.ts +++ b/test/e2e/module-layer/index.test.ts @@ -5,7 +5,7 @@ createNextDescribe( { files: __dirname, }, - ({ next, isNextStart }) => { + ({ next, isNextStart, isNextDev }) => { function runTests() { it('should render routes marked with restriction marks without errors', async () => { const routes = [ @@ -75,7 +75,7 @@ createNextDescribe( await next.patchFile( middlewareFile, middlewareContent - .replace("import 'server-only'", "// import 'server-only'") + // .replace("import 'server-only'", "// import 'server-only'") .replace("// import './lib/mixed-lib'", "import './lib/mixed-lib'") ) @@ -95,7 +95,11 @@ createNextDescribe( await next.patchFile(middlewareFile, middlewareContent) // await next.patchFile(pagesApiFile, pagesApiContent) }) - runTests() + + it('should error when import client-only in middleware', async () => { + const { status } = await next.fetch('/') + expect(status).toBe(500) + }) }) describe('with server-only in server targets', () => { runTests() From 6501af4a9ab64a419aee2b55d96e072eae8160b9 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Wed, 25 Oct 2023 15:17:21 -0700 Subject: [PATCH 3/3] add test --- test/e2e/module-layer/index.test.ts | 86 ++++++++++++++++------------- 1 file changed, 49 insertions(+), 37 deletions(-) diff --git a/test/e2e/module-layer/index.test.ts b/test/e2e/module-layer/index.test.ts index 26389eac72d27..701050aaaa34f 100644 --- a/test/e2e/module-layer/index.test.ts +++ b/test/e2e/module-layer/index.test.ts @@ -1,4 +1,5 @@ import { createNextDescribe } from 'e2e-utils' +import { getRedboxSource, hasRedbox } from 'next-test-utils' createNextDescribe( 'module layer', @@ -60,49 +61,60 @@ createNextDescribe( } } - describe('no server-only in server targets', () => { - const middlewareFile = 'middleware.js' - // const pagesApiFile = 'pages/api/hello.js' - let middlewareContent = '' - // let pagesApiContent = '' + describe('with server-only in server targets', () => { + runTests() + }) - beforeAll(async () => { - await next.stop() + // Should error for using mixed (with client-only) in server targets + if (isNextDev) { + describe('no server-only in server targets', () => { + const middlewareFile = 'middleware.js' + // const pagesApiFile = 'pages/api/hello.js' + let middlewareContent = '' + // let pagesApiContent = '' - middlewareContent = await next.readFile(middlewareFile) - // pagesApiContent = await next.readFile(pagesApiFile) + beforeAll(async () => { + await next.stop() - await next.patchFile( - middlewareFile, - middlewareContent - // .replace("import 'server-only'", "// import 'server-only'") - .replace("// import './lib/mixed-lib'", "import './lib/mixed-lib'") - ) + middlewareContent = await next.readFile(middlewareFile) + // pagesApiContent = await next.readFile(pagesApiFile) - // await next.patchFile( - // pagesApiFile, - // pagesApiContent - // .replace("import 'server-only'", "// import 'server-only'") - // .replace( - // "// import '../../lib/mixed-lib'", - // "import '../../lib/mixed-lib'" - // ) - // ) + await next.patchFile( + middlewareFile, + middlewareContent + // .replace("import 'server-only'", "// import 'server-only'") + .replace( + "// import './lib/mixed-lib'", + "import './lib/mixed-lib'" + ) + ) - await next.start() - }) - afterAll(async () => { - await next.patchFile(middlewareFile, middlewareContent) - // await next.patchFile(pagesApiFile, pagesApiContent) - }) + // await next.patchFile( + // pagesApiFile, + // pagesApiContent + // .replace("import 'server-only'", "// import 'server-only'") + // .replace( + // "// import '../../lib/mixed-lib'", + // "import '../../lib/mixed-lib'" + // ) + // ) + + await next.start() + }) + afterAll(async () => { + await next.patchFile(middlewareFile, middlewareContent) + // await next.patchFile(pagesApiFile, pagesApiContent) + }) - it('should error when import client-only in middleware', async () => { - const { status } = await next.fetch('/') - expect(status).toBe(500) + it('should error when import client-only in middleware', async () => { + const browser = await next.browser('/') + + expect(await hasRedbox(browser, true)).toBe(true) + expect(await getRedboxSource(browser)).toContain( + `You're importing a component that imports client-only. It only works in a Client Component but none of its parents are marked with "use client", so they're Server Components by default.` + ) + }) }) - }) - describe('with server-only in server targets', () => { - runTests() - }) + } } )