Skip to content
25 changes: 25 additions & 0 deletions packages/plugin-rsc/e2e/basic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,31 @@ test.describe('build-default', () => {
})
})

test.describe('build-server-client-chunks', () => {
const f = useFixture({
root: 'examples/basic',
mode: 'build',
cliOptions: {
env: {
TEST_SERVER_CLIENT_CHUNKS: 'true',
},
},
})

defineTest(f)

test('custom client chunk', async () => {
const { chunks }: { chunks: Rollup.OutputChunk[] } = JSON.parse(
f.createEditor('dist/client/.vite/test.json').read(),
)
const chunk = chunks.find((c) => c.name === 'root')
const expected = [1, 2, 3].map((i) =>
normalizePath(path.join(f.root, `src/routes/chunk/client${i}.tsx`)),
)
expect(chunk?.moduleIds).toEqual(expect.arrayContaining(expected))
})
})

test.describe('dev-non-optimized-cjs', () => {
test.beforeAll(async () => {
// remove explicitly added optimizeDeps.include
Expand Down
7 changes: 5 additions & 2 deletions packages/plugin-rsc/examples/basic/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,11 @@ export default defineConfig({
rscCssTransform: false,
copyServerAssetsToClient: (fileName) =>
fileName !== '__server_secret.txt',
clientChunks(id) {
if (id.includes('/src/routes/chunk/')) {
clientChunks(meta) {
if (process.env.TEST_SERVER_CLIENT_CHUNKS) {
return meta.serverChunk
}
if (meta.id.includes('/src/routes/chunk/')) {
return 'custom-chunk'
}
},
Expand Down
23 changes: 18 additions & 5 deletions packages/plugin-rsc/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ type ClientReferenceMeta = {
// build only for tree-shaking unused export
exportNames: string[]
renderedExports: string[]
serverChunk?: string
}

type ServerRerferenceMeta = {
Expand Down Expand Up @@ -185,10 +186,11 @@ export type RscPluginOptions = {
* This function allows you to group multiple client components into
* custom chunks instead of having each module in its own chunk.
*
* @param id - The absolute path of the client module
* @returns The chunk name to group this module with, or undefined to use default behavior
*/
clientChunks?: (id: string) => string | undefined
clientChunks?: (meta: {
id: string
serverChunk: string
}) => string | undefined
}

/** @experimental */
Expand Down Expand Up @@ -1145,13 +1147,18 @@ function vitePluginUseClient(
// group client reference modules by `clientChunks` option
manager.clientReferenceGroups = {}
for (const meta of Object.values(manager.clientReferenceMetaMap)) {
const name =
useClientPluginOptions.clientChunks?.(meta.importId) ||
let name =
useClientPluginOptions.clientChunks?.({
id: meta.importId,
serverChunk: meta.serverChunk!,
}) ??
// use original module id as name by default
normalizePath(path.relative(manager.config.root, meta.importId))
name = name.replaceAll('..', '__')
const group = (manager.clientReferenceGroups[name] ??= [])
group.push(meta)
}
debug('client-reference-groups', manager.clientReferenceGroups)
for (const [name, metas] of Object.entries(
manager.clientReferenceGroups,
)) {
Expand Down Expand Up @@ -1256,6 +1263,12 @@ function vitePluginUseClient(
const meta = manager.clientReferenceMetaMap[id]
if (meta) {
meta.renderedExports = mod.renderedExports
meta.serverChunk = normalizePath(
path.relative(
manager.config.root,
chunk.facadeModuleId ?? chunk.fileName,
),
)
}
}
}
Expand Down
Loading