Skip to content

Commit c26a2a3

Browse files
committed
fix: collect css with shared chunk name
1 parent 4a8d415 commit c26a2a3

File tree

8 files changed

+87
-3
lines changed

8 files changed

+87
-3
lines changed

.changeset/eight-months-camp.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@solidjs/start": patch
3+
---
4+
5+
Fixed CSS from shared chunks not being collected via the chunk name.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import "../../styles/sharedChunk.css";
2+
3+
export default () => {
4+
return <></>;
5+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default () => {
2+
return <></>;
3+
};

apps/fixtures/css/src/components/test.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,19 @@ export const CommonTests = (props: { routeModuleClass?: string }) => (
101101
</>
102102
}
103103
/>
104+
<Test
105+
component="SharedChunk"
106+
file="sharedChunk.css"
107+
class="sharedChunk"
108+
integration="import"
109+
lazy
110+
comment={
111+
<>
112+
Tests if CSS from shared chunks is server rendered properly. Rollup occasionally combines
113+
modules into such shared chunks.
114+
</>
115+
}
116+
/>
104117
</>
105118
);
106119

apps/fixtures/css/src/routes/index.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ const LazyLinkTmp = lazy(() => import("../components/lazyLinkTmp"));
1414
const entries = import.meta.glob("../components/lazyG*.tsx");
1515
const LazyGlob = lazy(Object.values(entries)[0] as any);
1616

17+
const SharedChunk = lazy(() => import("../components/sharedChunk/lazy1"));
18+
// Do not remove this.
19+
// Rollup only creates a shared chunk if there are atleast two modules.
20+
lazy(() => import("../components/sharedChunk/lazy2"));
21+
1722
const getData = query(async () => {
1823
"use server";
1924
await new Promise(res => setTimeout(res, 1000));
@@ -35,6 +40,7 @@ export default function Home() {
3540
<Show when={!data()}>
3641
<LazyLinkTmp />
3742
</Show>
43+
<SharedChunk />
3844

3945
<Layout title="CSS Tests">
4046
<CommonTests routeModuleClass={classes["route"]} />
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.sharedChunk {
2+
background-color: var(--color-success);
3+
}

apps/fixtures/css/vite.config.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,22 @@ import { solidStart } from "../../../packages/start/src/config";
55

66
export default defineConfig({
77
plugins: [solidStart(), nitroV2Plugin(), tailwindcss()],
8+
build: {
9+
rollupOptions: {
10+
output: {
11+
/**
12+
* Creates a shared chunk with two components. Needed for the "SharedChunk" test!
13+
* The vite manifest behaves differently for such shared chunks.
14+
* More info: packages/start/src/config/lazy.ts
15+
*
16+
* TODO: When switching to Rolldown, migrate this to advancedChunks
17+
* https://vite.dev/guide/rolldown.html#manualchunks-to-advancedchunks
18+
*/
19+
manualChunks(id) {
20+
if (!id.includes("src/components/sharedChunk")) return;
21+
return "shared";
22+
},
23+
},
24+
},
25+
},
826
});

packages/start/src/config/lazy.ts

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,43 @@ const fileEndingRegex = /(ts|js)x(\?.*)?$/;
4848

4949
const lazy = (): PluginOption => {
5050
const cwd = process.cwd().replaceAll(osSep, sep);
51+
52+
/**
53+
* Maps module ids to their client-specific shared chunk names.
54+
* Modules in shared chunks need to find their assets via the chunk name, instead of their module id.
55+
*
56+
* Vite includes assets of such modules in the manifest via the chunk name:
57+
* https://github.com/vitejs/vite/blob/4be37a8389c67873880f826b01fe40137e1c29a7/packages/vite/src/node/plugins/manifest.ts#L179
58+
* https://github.com/vitejs/vite/blob/4be37a8389c67873880f826b01fe40137e1c29a7/packages/vite/src/node/plugins/manifest.ts#L319
59+
*
60+
* Rollup occassionally creates shared chunks automatically,
61+
* but they can also be manually created by the user via:
62+
* https://rollupjs.org/configuration-options/#output-manualchunks
63+
*
64+
* More infos on Rollup's logic:
65+
* https://github.com/rollup/rollup/issues/3772#issuecomment-689955168
66+
*/
67+
const sharedChunkNames: Record<string, string> = {};
68+
5169
return {
5270
name: "solid-lazy-css",
5371
enforce: "pre",
54-
applyToEnvironment(env) {
55-
return env.name === VITE_ENVIRONMENTS.server;
72+
generateBundle(_, bundle) {
73+
if (this.environment.name !== VITE_ENVIRONMENTS.client) return;
74+
75+
for (const chunk of Object.values(bundle)) {
76+
if (chunk.type !== "chunk" || !chunk.isDynamicEntry || chunk.facadeModuleId) continue;
77+
78+
// Has to follow Vites implementation:
79+
// https://github.com/vitejs/vite/blob/4be37a8389c67873880f826b01fe40137e1c29a7/packages/vite/src/node/plugins/manifest.ts#L179
80+
const chunkName = `_${basename(chunk.fileName)}`;
81+
for (const id of chunk.moduleIds) {
82+
sharedChunkNames[id] = chunkName;
83+
}
84+
}
5685
},
5786
async transform(src, id) {
87+
if (this.environment.name !== VITE_ENVIRONMENTS.server) return;
5888
if (!id.match(fileEndingRegex)) return;
5989

6090
// The transformed files either import "lazy" or css files
@@ -66,7 +96,8 @@ const lazy = (): PluginOption => {
6696
const hasDefaultExport = src.indexOf("export default") !== -1;
6797
if (hasDefaultExport) {
6898
const localId = relative(cwd, id);
69-
plugins.push(idTransform(localId));
99+
const chunkName = sharedChunkNames[id];
100+
plugins.push(idTransform(chunkName ?? localId));
70101
}
71102

72103
const hasLazy = src.indexOf("lazy(") !== -1;

0 commit comments

Comments
 (0)