diff --git a/packages/plugin-rsc/e2e/basic.test.ts b/packages/plugin-rsc/e2e/basic.test.ts index c3a22d07..55903317 100644 --- a/packages/plugin-rsc/e2e/basic.test.ts +++ b/packages/plugin-rsc/e2e/basic.test.ts @@ -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 diff --git a/packages/plugin-rsc/examples/basic/vite.config.ts b/packages/plugin-rsc/examples/basic/vite.config.ts index f3883607..a3c76c7e 100644 --- a/packages/plugin-rsc/examples/basic/vite.config.ts +++ b/packages/plugin-rsc/examples/basic/vite.config.ts @@ -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' } }, diff --git a/packages/plugin-rsc/src/plugin.ts b/packages/plugin-rsc/src/plugin.ts index 54ea317e..f081de66 100644 --- a/packages/plugin-rsc/src/plugin.ts +++ b/packages/plugin-rsc/src/plugin.ts @@ -63,6 +63,7 @@ type ClientReferenceMeta = { // build only for tree-shaking unused export exportNames: string[] renderedExports: string[] + serverChunk?: string groupChunkId?: string } @@ -185,11 +186,13 @@ 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: { + /** client reference module id */ + id: string + /** server chunk which includes a corresponding client reference proxy module */ + serverChunk: string + }) => string | undefined } /** @experimental */ @@ -1148,7 +1151,10 @@ function vitePluginUseClient( manager.clientReferenceGroups = {} for (const meta of Object.values(manager.clientReferenceMetaMap)) { let name = - useClientPluginOptions.clientChunks?.(meta.importId) || + 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('..', '__') @@ -1261,6 +1267,14 @@ function vitePluginUseClient( const meta = manager.clientReferenceMetaMap[id] if (meta) { meta.renderedExports = mod.renderedExports + meta.serverChunk = + (chunk.facadeModuleId ? 'facade:' : 'non-facade:') + + normalizePath( + path.relative( + manager.config.root, + chunk.facadeModuleId ?? [...chunk.moduleIds].sort()[0]!, + ), + ) } } }