Skip to content

Commit

Permalink
Add optoutServerComponentsBundle option (#40770)
Browse files Browse the repository at this point in the history
Follow-up for #40739 to add an option to opt-out specific packages from being bundled.

## Bug

- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have a helpful link attached, see `contributing.md`

## Feature

- [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
- [ ] Related issues linked using `fixes #number`
- [x] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have a helpful link attached, see `contributing.md`

## Documentation / Examples

- [ ] Make sure the linting passes by running `pnpm lint`
- [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
  • Loading branch information
shuding committed Sep 24, 2022
1 parent 50ab2e4 commit d4d9d91
Show file tree
Hide file tree
Showing 11 changed files with 77 additions and 2 deletions.
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'

0 comments on commit d4d9d91

Please sign in to comment.