@@ -2,9 +2,16 @@ import assert from 'node:assert'
22import rsc , { transformHoistInlineDirective } from '@vitejs/plugin-rsc'
33import tailwindcss from '@tailwindcss/vite'
44import react from '@vitejs/plugin-react'
5- import { type Plugin , defineConfig , normalizePath , parseAstAsync } from 'vite'
5+ import {
6+ type Plugin ,
7+ type Rollup ,
8+ defineConfig ,
9+ normalizePath ,
10+ parseAstAsync ,
11+ } from 'vite'
612// import inspect from 'vite-plugin-inspect'
713import path from 'node:path'
14+ import { fileURLToPath } from 'node:url'
815
916export default defineConfig ( {
1017 clearScreen : false ,
@@ -88,6 +95,76 @@ export default defineConfig({
8895 }
8996 } ,
9097 } ,
98+ {
99+ name : 'optimize-chunks' ,
100+ apply : 'build' ,
101+ config ( ) {
102+ const resolvePackageSource = ( source : string ) =>
103+ normalizePath ( fileURLToPath ( import . meta. resolve ( source ) ) )
104+
105+ // TODO: this entrypoint shouldn't be a public API.
106+ const pkgBrowserPath = resolvePackageSource (
107+ '@vitejs/plugin-rsc/react/browser' ,
108+ )
109+
110+ return {
111+ environments : {
112+ client : {
113+ build : {
114+ rollupOptions : {
115+ output : {
116+ manualChunks : ( id ) => {
117+ // need to use functional form to handle commonjs plugin proxy module
118+ // e.g. `(id)?commonjs-es-import`
119+ if (
120+ id . includes ( 'node_modules/react/' ) ||
121+ id . includes ( 'node_modules/react-dom/' ) ||
122+ id . includes ( pkgBrowserPath )
123+ ) {
124+ return 'lib-react'
125+ }
126+ if ( id === '\0vite/preload-helper.js' ) {
127+ return 'lib-vite'
128+ }
129+ } ,
130+ } ,
131+ } ,
132+ } ,
133+ } ,
134+ } ,
135+ }
136+ } ,
137+ // verify chunks are "stable"
138+ writeBundle ( _options , bundle ) {
139+ if ( this . environment . name === 'client' ) {
140+ const entryChunks : Rollup . OutputChunk [ ] = [ ]
141+ const vendorChunks : Rollup . OutputChunk [ ] = [ ]
142+ for ( const chunk of Object . values ( bundle ) ) {
143+ if ( chunk . type === 'chunk' ) {
144+ if ( chunk . facadeModuleId ?. endsWith ( '/src/client.tsx' ) ) {
145+ entryChunks . push ( chunk )
146+ } else if ( chunk . name === 'lib-react' ) {
147+ vendorChunks . push ( chunk )
148+ }
149+ }
150+ }
151+
152+ // react vendor chunk has no import
153+ assert . equal ( vendorChunks . length , 1 )
154+ assert . deepEqual (
155+ vendorChunks [ 0 ] . imports . filter (
156+ ( f ) => ! f . includes ( 'rolldown-runtime' ) ,
157+ ) ,
158+ [ ] ,
159+ )
160+ assert . deepEqual ( vendorChunks [ 0 ] . dynamicImports , [ ] )
161+
162+ // entry chunk has no export
163+ assert . equal ( entryChunks . length , 1 )
164+ assert . deepEqual ( entryChunks [ 0 ] . exports , [ ] )
165+ }
166+ } ,
167+ } ,
91168 {
92169 name : 'cf-build' ,
93170 enforce : 'post' ,
0 commit comments