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, diff --git a/test/e2e/module-layer/index.test.ts b/test/e2e/module-layer/index.test.ts index 4aef0e35246fe..701050aaaa34f 100644 --- a/test/e2e/module-layer/index.test.ts +++ b/test/e2e/module-layer/index.test.ts @@ -1,11 +1,12 @@ import { createNextDescribe } from 'e2e-utils' +import { getRedboxSource, hasRedbox } from 'next-test-utils' createNextDescribe( 'module layer', { files: __dirname, }, - ({ next, isNextStart }) => { + ({ next, isNextStart, isNextDev }) => { function runTests() { it('should render routes marked with restriction marks without errors', async () => { const routes = [ @@ -60,45 +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 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.` + ) + }) }) - runTests() - }) - describe('with server-only in server targets', () => { - runTests() - }) + } } )