Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bundle ssr client layer excepts react externals #41606

Merged
merged 13 commits into from Oct 22, 2022
6 changes: 3 additions & 3 deletions package.json
Expand Up @@ -39,7 +39,6 @@
"lint-staged": "lint-staged",
"next-with-deps": "./scripts/next-with-deps.sh",
"next": "node --trace-deprecation --enable-source-maps packages/next/dist/bin/next",
"next-react-exp": "__NEXT_REACT_CHANNEL=exp node --trace-deprecation --enable-source-maps -r ./test/lib/react-channel-require-hook.js packages/next/dist/bin/next",
"next-no-sourcemaps": "node --trace-deprecation packages/next/dist/bin/next",
"clean-trace-jaeger": "rm -rf test/integration/basic/.next && TRACE_TARGET=JAEGER node --trace-deprecation --enable-source-maps packages/next/dist/bin/next build test/integration/basic",
"debug": "node --inspect packages/next/dist/bin/next",
Expand Down Expand Up @@ -179,10 +178,10 @@
"random-seed": "0.3.0",
"react": "18.2.0",
"react-17": "npm:react@17.0.2",
"react-builtin": "npm:react@0.0.0-experimental-9cdf8a99e-20221018",
"react-dom": "18.2.0",
"react-dom-17": "npm:react-dom@17.0.2",
"react-exp": "npm:react@0.0.0-experimental-9cdf8a99e-20221018",
"react-dom-exp": "npm:react-dom@0.0.0-experimental-9cdf8a99e-20221018",
"react-dom-builtin": "npm:react-dom@0.0.0-experimental-9cdf8a99e-20221018",
"react-server-dom-webpack": "0.0.0-experimental-9cdf8a99e-20221018",
"react-ssr-prepass": "1.0.8",
"react-virtualized": "9.22.3",
Expand All @@ -198,6 +197,7 @@
"shell-quote": "1.7.3",
"styled-components": "5.3.3",
"styled-jsx-plugin-postcss": "3.0.2",
"swr": "2.0.0-rc.0",
"tailwindcss": "1.1.3",
"taskr": "1.1.0",
"tree-kill": "1.2.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/next/build/entries.ts
Expand Up @@ -207,7 +207,7 @@ export function getEdgeServerEntry(opts: {
// The Edge bundle includes the server in its entrypoint, so it has to
// be in the SSR layer — we later convert the page request to the RSC layer
// via a webpack rule.
layer: undefined,
layer: WEBPACK_LAYERS.client,
}
}

Expand Down
5 changes: 0 additions & 5 deletions packages/next/build/index.ts
Expand Up @@ -120,7 +120,6 @@ import { RemotePattern } from '../shared/lib/image-config'
import { eventSwcPlugins } from '../telemetry/events/swc-plugins'
import { normalizeAppPath } from '../shared/lib/router/utils/app-paths'
import { AppBuildManifest } from './webpack/plugins/app-build-manifest-plugin'
import { verifyAppReactVersion } from '../lib/verifyAppReactVersion'

export type SsgRoute = {
initialRevalidateSeconds: number | false
Expand Down Expand Up @@ -307,10 +306,6 @@ export default async function build(
process.env.NEXT_PREBUNDLED_REACT = '1'
}
const { pagesDir, appDir } = findPagesDir(dir, isAppDirEnabled)

if (isAppDirEnabled) {
await verifyAppReactVersion({ dir })
}
const hasPublicDir = await fileExists(publicDir)

telemetry.record(
Expand Down
149 changes: 76 additions & 73 deletions packages/next/build/webpack-config.ts
Expand Up @@ -125,9 +125,11 @@ function isResourceInPackages(resource: string, packageNames?: string[]) {
)
}

const builtInReactImports = [
const bundledReactImports = [
'react',
'react/jsx-runtime',
'react/jsx-dev-runtime',
// 'react-dom',
'next/dist/compiled/react-server-dom-webpack/server.browser',
]

Expand Down Expand Up @@ -832,9 +834,6 @@ export default async function getBaseWebpackConfig(
[COMPILER_NAMES.edgeServer]: ['browser', 'module', 'main'],
}

const reactDir = path.dirname(require.resolve('react/package.json'))
const reactDomDir = path.dirname(require.resolve('react-dom/package.json'))

const resolveConfig = {
// Disable .mjs for node_modules bundling
extensions: isNodeServer
Expand Down Expand Up @@ -873,25 +872,19 @@ export default async function getBaseWebpackConfig(

next: NEXT_PROJECT_ROOT,

// Disable until pre-bundling is landed
// ...(hasServerComponents
// ? {
// // For react and react-dom, alias them dynamically for server layer
// // and others in the loaders configuration
// 'react-dom/client$': 'next/dist/compiled/react-dom/client',
// 'react-dom/server$': 'next/dist/compiled/react-dom/server',
// 'react-dom/server.browser$':
// 'next/dist/compiled/react-dom/server.browser',
// 'react/jsx-dev-runtime$':
// 'next/dist/compiled/react/jsx-dev-runtime',
// 'react/jsx-runtime$': 'next/dist/compiled/react/jsx-runtime',
// }
// : undefined),
react: reactDir,
'react-dom$': reactDomDir,
'react-dom/server$': `${reactDomDir}/server`,
'react-dom/server.browser$': `${reactDomDir}/server.browser`,
'react-dom/client$': `${reactDomDir}/client`,
...(hasServerComponents
? {
// For react and react-dom, alias them dynamically for server layer
// and others in the loaders configuration
'react-dom/client$': 'next/dist/compiled/react-dom/client',
'react-dom/server$': 'next/dist/compiled/react-dom/server',
'react-dom/server.browser$':
'next/dist/compiled/react-dom/server.browser',
'react/jsx-dev-runtime$':
'next/dist/compiled/react/jsx-dev-runtime',
'react/jsx-runtime$': 'next/dist/compiled/react/jsx-runtime',
}
: undefined),

'styled-jsx/style$': require.resolve(`styled-jsx/style`),
'styled-jsx$': require.resolve(`styled-jsx`),
Expand Down Expand Up @@ -1022,7 +1015,7 @@ export default async function getBaseWebpackConfig(
const crossOrigin = config.crossOrigin
const looseEsmExternals = config.experimental?.esmExternals === 'loose'

const optoutBundlingPackages = EXTERNAL_PACKAGES.concat(
const optOutBundlingPackages = EXTERNAL_PACKAGES.concat(
...(config.experimental.serverComponentsExternalPackages || [])
)

Expand Down Expand Up @@ -1057,7 +1050,7 @@ export default async function getBaseWebpackConfig(

// Special internal modules that must be bundled for Server Components.
if (layer === WEBPACK_LAYERS.server) {
if (builtInReactImports.includes(request)) {
if (bundledReactImports.includes(request)) {
return
}
}
Expand Down Expand Up @@ -1192,13 +1185,31 @@ export default async function getBaseWebpackConfig(
if (layer === WEBPACK_LAYERS.server) {
// All packages should be bundled for the server layer if they're not opted out.
// This option takes priority over the transpilePackages option.
if (isResourceInPackages(res, optoutBundlingPackages)) {
if (isResourceInPackages(res, optOutBundlingPackages)) {
return `${externalType} ${request}`
}

return
}

// Treat react packages as external for SSR layer,
// then let require-hook mapping them to internals.
if (layer === WEBPACK_LAYERS.client) {
if (
[
'react',
'react/jsx-runtime',
'react/jsx-dev-runtime',
'react-dom',
'scheduler',
].includes(request)
) {
return `commonjs next/dist/compiled/${request}`
} else {
return
}
}

if (shouldBeBundled) return

// Anything else that is standard JavaScript within `node_modules`
Expand Down Expand Up @@ -1564,24 +1575,19 @@ export default async function getBaseWebpackConfig(

return true
},
resolve: process.env.__NEXT_REACT_CHANNEL
? {
conditionNames: ['react-server', 'node', 'require'],
alias: {
react: `react-${process.env.__NEXT_REACT_CHANNEL}`,
'react-dom': `react-dom-${process.env.__NEXT_REACT_CHANNEL}`,
},
}
: {
conditionNames: ['react-server', 'node', 'require'],
alias: {
// If missing the alias override here, the default alias will be used which aliases
// react to the direct file path, not the package name. In that case the condition
// will be ignored completely.
react: 'react',
'react-dom': 'react-dom',
},
},
resolve: {
conditionNames: ['react-server', 'node', 'require'],
alias: {
// If missing the alias override here, the default alias will be used which aliases
// react to the direct file path, not the package name. In that case the condition
// will be ignored completely.
react: 'next/dist/compiled/react',
'react-dom$': isClient
? 'next/dist/compiled/react-dom/index'
: 'next/dist/compiled/react-dom/server-rendering-stub',
'react-dom/client$': 'next/dist/compiled/react-dom/client',
},
},
},
]
: []),
Expand All @@ -1608,7 +1614,6 @@ export default async function getBaseWebpackConfig(
},
]
: []),

...(hasServerComponents && !isClient
? [
// RSC server compilation loaders
Expand All @@ -1631,7 +1636,12 @@ export default async function getBaseWebpackConfig(
? [
{
test: codeCondition.test,
include: [appDir],
issuerLayer(layer: string) {
return (
layer === WEBPACK_LAYERS.client ||
layer === WEBPACK_LAYERS.server
)
},
resolve: {
alias: {
// Alias `next/dynamic` to React.lazy implementation for RSC
Expand All @@ -1645,16 +1655,15 @@ export default async function getBaseWebpackConfig(
// Alias react-dom for ReactDOM.preload usage.
// Alias react for switching between default set and share subset.
oneOf: [
/*
{
// test: codeCondition.test,
issuerLayer: WEBPACK_LAYERS.server,
test: (req: string) => {
test(req: string) {
// If it's not a source code file, or has been opted out of
// bundling, don't resolve it.
if (
!codeCondition.test.test(req) ||
isResourceInPackages(req, optoutBundlingPackages)
isResourceInPackages(req, optOutBundlingPackages)
) {
return false
}
Expand All @@ -1664,34 +1673,28 @@ export default async function getBaseWebpackConfig(
resolve: {
// It needs `conditionNames` here to require the proper asset,
// when react is acting as dependency of compiled/react-dom.
conditionNames: ['react-server', 'node', 'require'],
alias: {
react: 'react',
'react-dom': 'react-dom',
// Disable before prebundling is landed
// react: 'next/dist/compiled/react/react.shared-subset',
// // Use server rendering stub for RSC
// // x-ref: https://github.com/facebook/react/pull/25436
// 'react-dom$':
// 'next/dist/compiled/react-dom/server-rendering-stub',
react: 'next/dist/compiled/react/react.shared-subset',
// Use server rendering stub for RSC
// x-ref: https://github.com/facebook/react/pull/25436
'react-dom$':
'next/dist/compiled/react-dom/server-rendering-stub',
},
},
},
{
test: codeCondition.test,
resolve: {
alias: {
react: 'next/dist/compiled/react',
'react-dom$': isClient
? 'next/dist/compiled/react-dom/index'
: 'next/dist/compiled/react-dom/server-rendering-stub',
'react-dom/client$':
'next/dist/compiled/react-dom/client',
},
},
},
*/
// Disable before prebundling is landed
// {
// test: codeCondition.test,
// resolve: {
// alias: {
// react: 'next/dist/compiled/react',
// 'react-dom$': isClient
// ? 'next/dist/compiled/react-dom/index'
// : 'next/dist/compiled/react-dom/server-rendering-stub',
// 'react-dom/client$':
// 'next/dist/compiled/react-dom/client',
// },
// },
// },
],
},
]
Expand Down