Skip to content

Vinext doesn't do code splitting at all #740

@blitss

Description

@blitss

I'm trying to migrate from opennext, but one issue that stands out is that vinext doesn't do client bundle splitting at all. It produces one large bundle which contains every page, every route, etc.

Is there any way to fix it?
I'm using vite@8 since vite@7 fails build due Error: vinext: Failed to load @vitejs/plugin-react. at file:///home/codespace/next-frontend/node_modules/vinext/dist/index.js:568:10 { [cause]: Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './internal' is not defined by "exports" in /home/codespace/next-frontend/node_modules/vite/package.json imported from /home/codespace/next-frontend/node_modules/@vitejs/plugin-react/dist/index.js so i cant try it

I'm using same setup as in https://github.com/cloudflare/vinext/tree/main/examples/app-router-cloudflare

I've tried patching @vitejs/plugin-rsc and that helped, but I'm not sure if that's reliable patch. Should this be a vite rsc plugin issue? vinext issue?

Patch is:

diff --git a/dist/plugin.js b/dist/plugin.js
--- a/dist/plugin.js
+++ b/dist/plugin.js
@@ -805,25 +805,14 @@
 							};
 						}
 						let code = "";
-						manager.clientReferenceGroups = {};
 						for (const meta of Object.values(manager.clientReferenceMetaMap)) {
 							if (!meta.serverChunk) continue;
-							let name = useClientPluginOptions.clientChunks?.({
-								id: meta.importId,
-								normalizedId: manager.toRelativeId(meta.importId),
-								serverChunk: meta.serverChunk
-							}) ?? meta.serverChunk;
-							name = cleanUrl(name.replaceAll("..", "__"));
-							(manager.clientReferenceGroups[name] ??= []).push(meta);
-							meta.groupChunkId = `\0virtual:vite-rsc/client-references/group/${name}`;
-						}
-						debug("client-reference-groups", manager.clientReferenceGroups);
-						for (const [name, metas] of Object.entries(manager.clientReferenceGroups)) {
-							const groupVirtual = `virtual:vite-rsc/client-references/group/${name}`;
-							for (const meta of metas) code += `\
+							meta.groupChunkId = meta.importId;
+							const exports = meta.renderedExports.map((name) => `${JSON.stringify(name)}: m.${name},\n`).sort().join("");
+							code += `\
                 ${JSON.stringify(meta.referenceKey)}: async () => {
-                  const m = await import(${JSON.stringify(groupVirtual)});
-                  return m.export_${meta.referenceKey};
+                  const m = await import(${JSON.stringify(withResolvedIdProxy(meta.importId))});
+                  return {${exports}};
                 },
               `;
 						}
@@ -1465,4 +1454,4 @@
 }
 
 //#endregion
-export { vitePluginRsc as default, getPluginApi, transformRscCssExport, vitePluginRscMinimal };
\ No newline at end of file
+export { vitePluginRsc as default, getPluginApi, transformRscCssExport, vitePluginRscMinimal };

Before (worker-entry is largest bundle):

Build logs
codespace@coder-blits-blue-mackerel-8-6487658494-d7khz ~/next-frontend
 % bun run build
$ NODE_ENV=production bun run prepare && vinext build
$ panda codegen && panda cssgen --outfile styled-system/styles.css
✔️ `styled-system/css`: the css function to author styles
✔️ `styled-system/tokens`: the css variables and js function to query your tokens
✔️ `styled-system/patterns`: functions to implement and apply common layout patterns
✔️ `styled-system/jsx`: styled jsx elements for react


🐼 info [css] /home/codespace/next-frontend/styled-system/styles.css
🐼 info [hrtime] Successfully extracted css from 133 file(s) ✨ (76.29ms)

  vinext build  (Vite 8.0.3)

[vinext] Found 1 external rewrite that proxy requests to external origins:
  /graphql → https://api.streamloop.app/graphql
Request headers, including credential headers (cookie, authorization, proxy-authorization, x-api-key), are forwarded to the external origin to match Next.js behavior. If you do not want to forward credentials, use an API route or route handler where you control exactly which headers are sent.
[vinext] middleware.ts is deprecated in Next.js 16. Rename to proxy.ts and export a default or named proxy function.
[1/5] analyze client references...
transforming (188) src/components/stream-list/stream-list.page.tsx[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "map" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "BehaviorSubject" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "of" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "EMPTY" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "Observable" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "distinctUntilChanged" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "EMPTY" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "Observable" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "map" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "Observable" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "catchError" in barrel export map
transforming (306) node_modules/graphql/jsutils/devAssert.mjs[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "filter" in barrel export map
✓ 508 modules transformed.
✓ built in 751ms
[2/5] analyze server references...
transforming (298) node_modules/framer-motion/dist/es/index.mjs[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "Observable" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "asapScheduler" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "filter" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "map" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "BehaviorSubject" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "EMPTY" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "Observable" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "distinctUntilChanged" in barrel export map
transforming (413) node_modules/@apollo/client/react/hooks/useQuery.js[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "EMPTY" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "Observable" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "catchError" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "Observable" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "map" in barrel export map
✓ 2517 modules transformed.
✓ built in 1.08s
[3/5] build rsc environment...
transforming (164) src/components/ui/button.tsx[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "of" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "map" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "BehaviorSubject" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "EMPTY" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "Observable" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "distinctUntilChanged" in barrel export map
transforming (298) node_modules/@apollo/client-react-streaming/dist/index.rsc.js[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "EMPTY" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "map" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "Observable" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "Observable" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "catchError" in barrel export map
transforming (657) node_modules/rxjs/dist/cjs/internal/scheduler/animationFrameProvider.js[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "filter" in barrel export map
✓ 757 modules transformed.
computing gzip size...
[IMPORT_IS_UNDEFINED] Warning: Import `default` will always be undefined because there is no matching export in 'src/middleware.ts'
      ╭─[ \0virtual:vinext-rsc-entry:2060:39 ]
      │
 2060 │     : (middlewareModule.middleware ?? middlewareModule.default);
      │                                       ────────────┬───────────  
      │                                                   ╰───────────── 
──────╯

✓ built in 830ms
[4/5] build client environment...
Warning: Invalid input options (1 issue found)
- For the "treeshake.preset". Invalid key: Expected never but received "preset". 
✓ 4468 modules transformed.
computing gzip size...
[plugin builtin:vite-reporter] 
(!) Some chunks are larger than 500 kB after minification. Consider:
- Using dynamic import() to code-split the application
- Use build.rolldownOptions.output.codeSplitting to improve chunking: https://rolldown.rs/reference/OutputOptions.codeSplitting
- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.
✓ built in 1.67s
[5/5] build ssr environment...
transforming (470) styled-system/patterns/flex.mjs[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "Observable" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "asapScheduler" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "filter" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "map" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "BehaviorSubject" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "EMPTY" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "distinctUntilChanged" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "Observable" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "EMPTY" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "Observable" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "map" in barrel export map
transforming (1348) node_modules/@apollo/client/link/subscriptions/index.js[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "Observable" in barrel export map
[vinext:optimize-imports] skipping "rxjs": could not resolve specifier "catchError" in barrel export map
✓ 2592 modules transformed.
computing gzip size...
✓ built in 1.68s
[vinext] Found 1 external rewrite that proxy requests to external origins:
  /graphql → https://api.streamloop.app/graphql
Request headers, including credential headers (cookie, authorization, proxy-authorization, x-api-key), are forwarded to the external origin to match Next.js behavior. If you do not want to forward credentials, use an API route or route handler where you control exactly which headers are sent.

  Route (app)
  ┌ ? /                       
  ├ ? /account                
  ├ ? /account/settings       
  ├ ? /admin/users            
  ├ λ /api/aaguid-icon/:aaguid
  ├ λ /api/aaguid-name/:aaguid
  ├ λ /api/avatar/:key        
  ├ λ /api/revalidate         
  ├ ? /auth/callback          
  ├ ? /auth/login             
  ├ ? /auth/recovery          
  ├ ? /auth/signup            
  ├ ? /auth/verification      
  ├ ? /auth/welcome           
  ├ ? /billing                
  ├ ? /loops                  
  ├ ƒ /loops/:id              
  ├ ? /loops/new              
  ├ ? /privacy                
  └ ? /terms                  

  λ API  ƒ Dynamic  ? Unknown

  ? Some routes could not be classified. vinext currently uses static analysis
    and cannot detect dynamic API usage (headers(), cookies(), etc.) at build time.
    Automatic classification will be improved in a future release.

  Build complete. Run `vinext start` to start the production server.
Image

After:

Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions