Skip to content

Commit 4297c64

Browse files
committed
chore(rsc): custom client chunks
1 parent ed91da6 commit 4297c64

File tree

8 files changed

+404
-262
lines changed

8 files changed

+404
-262
lines changed

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,13 @@
2626
"react": "^19.1.0",
2727
"react-dom": "^19.1.0",
2828
"react-server-dom-webpack": "^19.1.0",
29+
"rollup": "^4.41.1",
2930
"tsdown": "0.7.3",
3031
"tsup": "^8.3.6",
3132
"tsx": "^4.19.3",
3233
"typescript": "^5.8.3",
3334
"unplugin-isolated-decl": "^0.13.5",
34-
"vite": "^6.3.2",
35+
"vite": "^6.3.5",
3536
"vite-plugin-inspect": "^11.0.1",
3637
"vitest": "^3.1.1",
3738
"wrangler": "^4.13.0"
@@ -42,6 +43,7 @@
4243
},
4344
"pnpm": {
4445
"overrides": {
46+
"rollup": "$rollup",
4547
"vite": "$vite",
4648
"react": "$react",
4749
"react-dom": "$react-dom",
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
"use client";
2+
3+
export function TestClientChunk1() {
4+
return <span>test-chunk1</span>;
5+
}
6+
7+
export function TestClientChunkConflict() {
8+
return <span>test-chunk-confclit1</span>;
9+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
"use client";
2+
3+
export function TestClientChunk2() {
4+
return <span>test-chunk2</span>;
5+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
"use client";
2+
3+
export function TestClientChunk3() {
4+
return <span>test-chunk3</span>;
5+
}
6+
7+
export function TestClientChunkConflict() {
8+
return <span>test-chunk-confclit3</span>;
9+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import {
2+
TestClientChunk1,
3+
TestClientChunkConflict as TestClientChunkConflict1,
4+
} from "./client1";
5+
import { TestClientChunk2 } from "./client2";
6+
import {
7+
TestClientChunk3,
8+
TestClientChunkConflict as TestClientChunkConflict3,
9+
} from "./client3";
10+
11+
export function TestClientChunkServer() {
12+
return (
13+
<div>
14+
<TestClientChunk1 />|
15+
<TestClientChunkConflict1 />|
16+
<TestClientChunk2 />|
17+
<TestClientChunk3 />|
18+
<TestClientChunkConflict3 />
19+
</div>
20+
);
21+
}

packages/rsc/examples/basic/src/routes/root.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
TestServerActionBindReset,
2626
TestServerActionBindSimple,
2727
} from "./action-bind/server";
28+
import { TestClientChunkServer } from "./chunks/server";
2829
import styles from "./server.module.css";
2930

3031
export function Root(props: { url: URL }) {
@@ -78,6 +79,7 @@ export function Root(props: { url: URL }) {
7879
<TestServerActionBindSimple />
7980
<TestServerActionBindClient />
8081
<TestServerActionBindAction />
82+
<TestClientChunkServer />
8183
</body>
8284
</html>
8385
);

packages/rsc/examples/basic/vite.config.ts

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import assert from "node:assert";
2+
import { fileURLToPath } from "node:url";
23
import rsc from "@hiogawa/vite-rsc/plugin";
34
import tailwindcss from "@tailwindcss/vite";
45
import react from "@vitejs/plugin-react";
5-
import { defineConfig } from "vite";
6+
import { type Rollup, defineConfig, normalizePath } from "vite";
67
import Inspect from "vite-plugin-inspect";
78

89
export default defineConfig({
@@ -100,6 +101,74 @@ export default { fetch: handler };
100101
}
101102
},
102103
},
104+
{
105+
name: "optimize-chunks",
106+
apply: "build",
107+
config() {
108+
const resolvePackageSource = (source: string) =>
109+
normalizePath(fileURLToPath(import.meta.resolve(source)));
110+
111+
const pkgBrowserPath = resolvePackageSource(
112+
"@hiogawa/vite-rsc/browser",
113+
);
114+
115+
// Non-functional form cannot handle commonjs plugin module
116+
// e.g. `(id)?commonjs-es-import`
117+
// manualChunks: {
118+
// "lib-react": [
119+
// "react",
120+
// "react/jsx-runtime",
121+
// "react-dom/client",
122+
// "react-server-dom-webpack/client.browser",
123+
// ],
124+
// }
125+
126+
const manualChunksFn: Rollup.ManualChunksOption = (id, meta) => {
127+
// users can merge client reference chunks by own heuristics
128+
if (id.startsWith("\0virtual:vite-rsc/build-client-reference/")) {
129+
const info = meta.getModuleInfo(id)!;
130+
const originalId = info.importedIds[0]!;
131+
// e.g. group by directory
132+
if (originalId.includes("/src/routes/chunks/")) {
133+
return "rsc-custom";
134+
}
135+
}
136+
137+
// similar to
138+
// https://github.com/web-infra-dev/rsbuild/blob/main/packages/plugin-react/src/splitChunks.ts
139+
if (
140+
id.includes("node_modules/react/") ||
141+
id.includes("node_modules/react/") ||
142+
id.includes("node_modules/react-dom/") ||
143+
id.includes("node_modules/react-server-dom-webpack/")
144+
) {
145+
return "lib-react";
146+
}
147+
148+
if (
149+
id === "\0virtual:vite-rsc/entry-browser" ||
150+
id === pkgBrowserPath
151+
) {
152+
return "rsc-entry";
153+
}
154+
};
155+
156+
return {
157+
environments: {
158+
client: {
159+
build: {
160+
manifest: true,
161+
rollupOptions: {
162+
output: {
163+
manualChunks: manualChunksFn,
164+
},
165+
},
166+
},
167+
},
168+
},
169+
};
170+
},
171+
},
103172
],
104173
build: {
105174
minify: false,

0 commit comments

Comments
 (0)