Skip to content

Commit

Permalink
Alias next/head to noop for rsc and add upgration warning (#43885)
Browse files Browse the repository at this point in the history
This will reduce the bundle size and also give user proper hint to upgrade to `head.js`

* Mark `next/head` as noop in app dir
* Add warning for users to check the upgration guide to migrate it to head.js
  • Loading branch information
huozhi committed Dec 9, 2022
1 parent 5f27b9d commit a7f2910
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 0 deletions.
21 changes: 21 additions & 0 deletions packages/next/build/webpack-config.ts
Expand Up @@ -98,6 +98,14 @@ const BABEL_CONFIG_FILES = [
'babel.config.cjs',
]

function appDirIssuerLayer(layer: string) {
return (
layer === WEBPACK_LAYERS.client ||
layer === WEBPACK_LAYERS.server ||
layer === WEBPACK_LAYERS.appClient
)
}

export const getBabelConfigFile = async (dir: string) => {
const babelConfigFile = await BABEL_CONFIG_FILES.reduce(
async (memo: Promise<string | undefined>, filename) => {
Expand Down Expand Up @@ -1709,6 +1717,19 @@ export default async function getBaseWebpackConfig(
: []),
...(hasServerComponents
? [
// Alias next/head component to noop for RSC
{
test: codeCondition.test,
issuerLayer: appDirIssuerLayer,
resolve: {
alias: {
// Alias `next/dynamic` to React.lazy implementation for RSC
[require.resolve('next/head')]: require.resolve(
'next/dist/client/components/noop-head'
),
},
},
},
{
// Alias react-dom for ReactDOM.preload usage.
// Alias react for switching between default set and share subset.
Expand Down
11 changes: 11 additions & 0 deletions packages/next/client/components/noop-head.tsx
@@ -0,0 +1,11 @@
import { warnOnce } from '../../shared/lib/utils/warn-once'

if (process.env.NODE_ENV !== 'production') {
warnOnce(
`You're using \`next/head\` inside app directory, please migrate to \`head.js\`. Checkout https://beta.nextjs.org/docs/api-reference/file-conventions/head for details.`
)
}

export default function NoopHead() {
return null
}
32 changes: 32 additions & 0 deletions test/e2e/app-dir/head.test.ts
@@ -1,9 +1,11 @@
import fs from 'fs-extra'
import path from 'path'
import cheerio from 'cheerio'
import { createNext, FileRef } from 'e2e-utils'
import { NextInstance } from 'test/lib/next-modes/base'
import { renderViaHTTP } from 'next-test-utils'
import webdriver from 'next-webdriver'
import escapeStringRegexp from 'escape-string-regexp'

describe('app dir head', () => {
if ((global as any).isNextDeploy) {
Expand Down Expand Up @@ -115,8 +117,38 @@ describe('app dir head', () => {
})

it('should treat next/head as client components but not apply', async () => {
const errors = []
next.on('stderr', (args) => {
errors.push(args)
})
const html = await renderViaHTTP(next.url, '/next-head')
expect(html).not.toMatch(/<title>legacy-head<\/title>/)

if (globalThis.isNextDev) {
expect(
errors.some(
(output) =>
output ===
`You're using \`next/head\` inside app directory, please migrate to \`head.js\`. Checkout https://beta.nextjs.org/docs/api-reference/file-conventions/head for details.\n`
)
).toBe(true)

const dynamicChunkPath = path.join(
next.testDir,
'.next',
'static/chunks/_app-client_app_next-head_client-head_js.js'
)
const content = await fs.readFile(dynamicChunkPath, 'utf-8')
expect(content).not.toMatch(
new RegExp(escapeStringRegexp(`next/dist/shared/lib/head.js`), 'm')
)
expect(content).toMatch(
new RegExp(
escapeStringRegexp(`next/dist/client/components/noop-head.js`),
'm'
)
)
}
})
}

Expand Down
9 changes: 9 additions & 0 deletions test/e2e/app-dir/head/app/next-head/client-head.js
@@ -0,0 +1,9 @@
import Head from 'next/head'

export default function ClientHead() {
return (
<Head>
<meta content="dynamic" property="dynamic-head" />
</Head>
)
}
7 changes: 7 additions & 0 deletions test/e2e/app-dir/head/app/next-head/dynamic-head.js
@@ -0,0 +1,7 @@
'use client'

import dynamic from 'next/dynamic'

const ClientHead = dynamic(() => import('./client-head'), { ssr: false })

export default ClientHead
2 changes: 2 additions & 0 deletions test/e2e/app-dir/head/app/next-head/page.js
@@ -1,11 +1,13 @@
import Head from 'next/head'
import DynamicHead from './dynamic-head'

export default function page() {
return (
<>
<Head>
<title>legacy-head</title>
</Head>
<DynamicHead />
<p>page</p>
</>
)
Expand Down

0 comments on commit a7f2910

Please sign in to comment.