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

Add optoutServerComponentsBundle option #40770

Merged
merged 6 commits into from Sep 24, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 10 additions & 2 deletions packages/next/build/webpack-config.ts
Expand Up @@ -1021,7 +1021,7 @@ export default async function getBaseWebpackConfig(
})
: null

// Special internal modules that must be bundled for Server Components.
// Special internal modules that require to be bundled for Server Components.
if (layer === WEBPACK_LAYERS.server) {
if (!isLocal && /^react(?:$|\/)/.test(request)) {
const [resolved] = await resolveWithReactServerCondition!(
Expand Down Expand Up @@ -1158,7 +1158,15 @@ export default async function getBaseWebpackConfig(
}

if (/node_modules[/\\].*\.[mc]?js$/.test(res)) {
if (layer === WEBPACK_LAYERS.server) {
if (
layer === WEBPACK_LAYERS.server &&
(!config.experimental?.optoutServerComponentsBundle ||
!config.experimental?.optoutServerComponentsBundle.some(
// Check if a package is opt-out of Server Components bundling.
(packageName) =>
new RegExp(`node_modules[/\\\\]${packageName}[/\\\\]`).test(res)
))
) {
try {
const [resolved] = await resolveWithReactServerCondition!(
context,
Expand Down
4 changes: 4 additions & 0 deletions packages/next/server/config-shared.ts
Expand Up @@ -150,6 +150,10 @@ export interface ExperimentalConfig {
algorithm?: SubresourceIntegrityAlgorithm
}
adjustFontFallbacks?: boolean

// A list of packages that should be treated as external in the RSC server build
optoutServerComponentsBundle?: string[]

fontLoaders?: { [fontLoader: string]: any }
}

Expand Down
12 changes: 12 additions & 0 deletions test/e2e/app-dir/rsc-basic.test.ts
Expand Up @@ -418,6 +418,18 @@ describe('app dir - react server components', () => {
)
})

it('should be able to opt-out 3rd party packages being bundled in server components', async () => {
await fetchViaHTTP(next.url, '/react-server/optout').then(
async (response) => {
const result = await resolveStreamResponse(response)
expect(result).toContain('Server: index.default')
expect(result).toContain('Server subpath: subpath.default')
expect(result).toContain('Client: index.default')
expect(result).toContain('Client subpath: subpath.default')
}
)
})

if (!isNextDev) {
it('should generate edge SSR manifests for Node.js', async () => {
const distServerDir = path.join(distDir, 'server')
Expand Down
15 changes: 15 additions & 0 deletions test/e2e/app-dir/rsc-basic/app/react-server/optout/client.js
@@ -0,0 +1,15 @@
'client'

import v from 'conditional-exports-optout'
import v1 from 'conditional-exports-optout/subpath'

export default function Client() {
return (
<>
{`Client: ${v}`}
<br />
{`Client subpath: ${v1}`}
<br />
</>
)
}
16 changes: 16 additions & 0 deletions test/e2e/app-dir/rsc-basic/app/react-server/optout/page.js
@@ -0,0 +1,16 @@
import v from 'conditional-exports-optout'
import v1 from 'conditional-exports-optout/subpath'

import Client from './client'

export default function Page() {
return (
<div>
{`Server: ${v}`}
<br />
{`Server subpath: ${v1}`}
<br />
<Client />
</div>
)
}
1 change: 1 addition & 0 deletions test/e2e/app-dir/rsc-basic/next.config.js
Expand Up @@ -5,6 +5,7 @@ module.exports = {
},
experimental: {
appDir: true,
optoutServerComponentsBundle: ['conditional-exports-optout'],
},
rewrites: async () => {
return {
Expand Down
@@ -0,0 +1 @@
module.exports = 'index.default'
@@ -0,0 +1 @@
module.exports = 'index.react-server'
@@ -0,0 +1,15 @@
{
"name": "conditional-exports-optout",
"main": "index.js",
"exports": {
".": {
"react-server": "./index.server.js",
"default": "./index.js"
},
"./subpath": {
"react-server": "./subpath.server.js",
"default": "./subpath.js"
},
"./package.json": "./package.json"
}
}
@@ -0,0 +1 @@
module.exports = 'subpath.default'
@@ -0,0 +1 @@
module.exports = 'subpath.react-server'