diff --git a/packages/next-swc/crates/core/src/react_server_components.rs b/packages/next-swc/crates/core/src/react_server_components.rs index 5322e9bef98e..81ad12f596df 100644 --- a/packages/next-swc/crates/core/src/react_server_components.rs +++ b/packages/next-swc/crates/core/src/react_server_components.rs @@ -111,7 +111,7 @@ impl ReactServerComponents { return false; } } - // Match `ParenthesisExpression` which is some formartting tools + // Match `ParenthesisExpression` which is some formatting tools // usually do: ('use client'). In these case we need to throw // an exception because they are not valid directives. Expr::Paren(ParenExpr { expr, .. }) => { diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index 4d7df85fd41a..650a6b31d446 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -1151,15 +1151,16 @@ export default async function getBaseWebpackConfig( const isLocalCallback = (localRes: string) => { // Makes sure dist/shared and dist/server are not bundled - // we need to process shared `router/router` and `dynamic`, - // so that the DefinePlugin can inject process.env values + // we need to process shared `router/router`, `head` and `dynamic`, + // so that the DefinePlugin can inject process.env values. + + // Treat next internals as non-external for server layer + if (layer === WEBPACK_LAYERS.server) return + const isNextExternal = - // Treat next internals as non-external for server layer - layer === WEBPACK_LAYERS.server - ? false - : /next[/\\]dist[/\\](esm[\\/])?(shared|server)[/\\](?!lib[/\\](router[/\\]router|dynamic))/.test( - localRes - ) + /next[/\\]dist[/\\](esm[\\/])?(shared|server)[/\\](?!lib[/\\](router[/\\]router|dynamic|head[^-]))/.test( + localRes + ) if (isNextExternal) { // Generate Next.js external import @@ -1176,10 +1177,6 @@ export default async function getBaseWebpackConfig( .replace(/\\/g, '/') ) return `commonjs ${externalRequest}` - } else if (layer !== WEBPACK_LAYERS.client) { - // We don't want to retry local requests - // with other preferEsm options - return } } diff --git a/test/e2e/app-dir/app/app/internal/page.js b/test/e2e/app-dir/app/app/internal/page.js index 134daec5bbb4..525104c574ac 100644 --- a/test/e2e/app-dir/app/app/internal/page.js +++ b/test/e2e/app-dir/app/app/internal/page.js @@ -1,14 +1,9 @@ import Link from 'next/link' -import Head from 'next/head' export default function Page() { return (
- {/* NOTE: next/head will not work in RSC for now but not break either */} - - internal-title - Navigate Rewrite diff --git a/test/e2e/app-dir/head.test.ts b/test/e2e/app-dir/head.test.ts index dfd4c126cd05..c441577a54bf 100644 --- a/test/e2e/app-dir/head.test.ts +++ b/test/e2e/app-dir/head.test.ts @@ -113,6 +113,11 @@ describe('app dir head', () => { .waitForElementByCss('#layout', 2000) expect(await getTitle()).toBe('hello from dynamic blog page post-1') }) + + it('should treat next/head as client components but not apply', async () => { + const html = await renderViaHTTP(next.url, '/next-head') + expect(html).not.toMatch(/legacy-head<\/title>/) + }) } runTests() diff --git a/test/e2e/app-dir/head/app/next-head/page.js b/test/e2e/app-dir/head/app/next-head/page.js new file mode 100644 index 000000000000..e55823f8d945 --- /dev/null +++ b/test/e2e/app-dir/head/app/next-head/page.js @@ -0,0 +1,12 @@ +import Head from 'next/head' + +export default function page() { + return ( + <> + <Head> + <title>legacy-head + +

page

+ + ) +} diff --git a/test/integration/externalize-next-server/test/index.test.js b/test/integration/externalize-next-server/test/index.test.js index bad17940528b..c88f4627c1fd 100644 --- a/test/integration/externalize-next-server/test/index.test.js +++ b/test/integration/externalize-next-server/test/index.test.js @@ -10,9 +10,19 @@ describe('externalize next/dist/shared', () => { await nextBuild(appDir) }) - it('Does not bundle next/dist/shared/lib/head.js in _error', async () => { + it('Bundle next/dist/shared/lib/head.js but not next/dist/shared/lib/head-manager-context.js in _error', async () => { const content = readNextBuildServerPageFile(appDir, '/_error') expect(content).toMatch( + new RegExp( + '^' + + escapeStringRegexp( + `module.exports = require("next/dist/shared/lib/head-manager-context.js");` + ) + + ';?$', + 'm' + ) + ) + expect(content).not.toMatch( new RegExp( '^' + escapeStringRegexp(