Skip to content

Commit 1afe9eb

Browse files
committed
generate client manifest data properly
1 parent a930638 commit 1afe9eb

8 files changed

Lines changed: 72 additions & 52 deletions

File tree

packages/start/src/config/index.ts

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,6 @@ function solidStartVitePlugin(options?: SolidStartOptions): Array<PluginOption>
264264
const manifest: StartServerManifest = {
265265
clientEntryId: normalizePath(handlers.client),
266266
clientViteManifest: {},
267-
clientManifestData: {}
268267
};
269268

270269
return `export const manifest = ${JSON.stringify(manifest)}`;
@@ -279,39 +278,9 @@ function solidStartVitePlugin(options?: SolidStartOptions): Array<PluginOption>
279278
(globalThis.START_CLIENT_BUNDLE[".vite/manifest.json"] as any).source
280279
);
281280

282-
const clientAssetManifest = Object.entries(clientManifest).reduce((acc, [id, entry]) => {
283-
const assets = [
284-
...(entry.assets?.filter(Boolean) || []),
285-
...(entry.css?.filter(Boolean) || [])
286-
]
287-
.filter(
288-
asset => asset.endsWith(".css") || asset.endsWith(".js") || asset.endsWith(".mjs")
289-
)
290-
.map(
291-
asset =>
292-
({
293-
tag: "link",
294-
attrs: {
295-
href: join("/", CLIENT_BASE_PATH, asset),
296-
key: join("/", CLIENT_BASE_PATH, asset),
297-
...(asset.endsWith(".css")
298-
? { rel: "stylesheet", fetchPriority: "high" }
299-
: { rel: "modulepreload" })
300-
}
301-
} satisfies ManifestAsset)
302-
);
303-
304-
acc[id] = {
305-
output: `/${CLIENT_BASE_PATH}/${entry.file}`,
306-
assets
307-
};
308-
return acc;
309-
}, {} as ClientManifest);
310-
311281
const manifest: StartServerManifest = {
312282
clientEntryId: normalizePath(handlers.client),
313283
clientViteManifest: clientManifest as any,
314-
clientManifestData: clientAssetManifest
315284
};
316285

317286
return `export const manifest = ${JSON.stringify(manifest)};`;
@@ -325,7 +294,7 @@ function solidStartVitePlugin(options?: SolidStartOptions): Array<PluginOption>
325294
throw new Error("Missing id to get assets.");
326295
}
327296
return `export default ${JSON.stringify(
328-
await getSsrDevManifest(true, handlers.client).getAssets(id)
297+
await getSsrDevManifest("server").getAssets(id)
329298
)}`;
330299
}
331300
} else if (id === `\0${VIRTUAL_MODULES.middleware}`) return "export default {};"

packages/start/src/server/StartServer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ export function StartServer(props: { document: Component<DocumentComponentProps>
9191
<>
9292
<script
9393
nonce={nonce}
94-
innerHTML={`window.manifest = ${JSON.stringify(manifest.clientManifestData)}`}
94+
innerHTML={`window.manifest = ${JSON.stringify(context.manifest)}`}
9595
/>
9696
<script type="module" nonce={nonce} async src={getClientEntryPath()} />
9797
</>

packages/start/src/server/handler.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import type { JSX } from "solid-js";
44
import { sharedConfig } from "solid-js";
55
import { renderToStream, renderToString } from "solid-js/web";
66
import { provideRequestEvent } from "solid-js/web/storage";
7-
import { getSsrManifest } from "solid-start:get-ssr-manifest";
87
import middleware from "solid-start:middleware";
98

109
import { createRoutes } from "../router.jsx";
@@ -13,6 +12,7 @@ import { matchAPIRoute } from "./routes.js";
1312
import { handleServerFunction } from "./server-functions-handler.js";
1413
import { getClientEntryCssTags } from "./server-manifest.js";
1514
import type { APIEvent, FetchEvent, HandlerOptions, PageEvent } from "./types.js";
15+
import { getSsrManifest } from "./manifest/ssr-manifest.js";
1616

1717
const SERVER_FN_BASE = "/_server";
1818

@@ -106,8 +106,9 @@ export async function createPageEvent(ctx: FetchEvent) {
106106
ctx.response.headers.set("Content-Type", "text/html");
107107
// const prevPath = ctx.request.headers.get("x-solid-referrer");
108108
// const mutation = ctx.request.headers.get("x-solid-mutation") === "true";
109+
const manifest = getSsrManifest('client');
109110
const pageEvent: PageEvent = Object.assign(ctx, {
110-
manifest: getSsrManifest(false),
111+
manifest: 'json' in manifest ? await manifest.json() : {},
111112
assets: [
112113
...(await getClientEntryCssTags())
113114
// ...(import.meta.env.START_ISLANDS

packages/start/src/server/manifest/dev-server-manifest.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { ViteDevServer } from "vite";
33

44
import { findStylesInModuleGraph } from "../collect-styles.js";
55

6-
export function getSsrDevManifest(ssr: boolean, clientEntryId: string): StartManifest {
6+
export function getSsrDevManifest(target: "client" | "server") {
77
const vite: ViteDevServer = (globalThis as any).VITE_DEV_SERVER;
88

99
return {
@@ -12,7 +12,7 @@ export function getSsrDevManifest(ssr: boolean, clientEntryId: string): StartMan
1212
return vite.ssrLoadModule(join(absolutePath));
1313
},
1414
async getAssets(id: string) {
15-
const styles = await findStylesInModuleGraph(vite, id, ssr);
15+
const styles = await findStylesInModuleGraph(vite, id, target === "server");
1616

1717
return Object.entries(styles).map(([key, value]) => ({
1818
tag: "style",
@@ -25,10 +25,6 @@ export function getSsrDevManifest(ssr: boolean, clientEntryId: string): StartMan
2525
children: value,
2626
}));
2727
},
28-
// handler() {
29-
// if (ssr) throw new Error("Not implemented");
30-
// return normalizePath(path.join("/@fs", path.resolve(process.cwd(), clientEntryId)));
31-
// }
3228
} satisfies StartManifest;
3329
}
3430

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
import { manifest } from "solid-start:server-manifest"
22
import { join } from "pathe";
33

4+
// Only reads from client manifest atm, might need server support for islands
45
export function getSsrProdManifest() {
56
const viteManifest = manifest.clientViteManifest;
67
return {
78
import(id) {
89
return import(/* @vite-ignore */ id);
910
},
1011
async getAssets(id) {
11-
return []
12+
return createHtmlTagsForAssets(
13+
findAssetsInViteManifest(manifest.clientViteManifest, id),
14+
);
1215
},
1316
async json() {
1417
const json: Record<string, any> = {};
@@ -19,11 +22,66 @@ export function getSsrProdManifest() {
1922

2023
for (const entryKey of entryKeys) {
2124
json[entryKey] = {
22-
output: join(viteManifest[entryKey]!.file)
23-
}
25+
output: join("/", CLIENT_BASE_PATH, viteManifest[entryKey]!.file),
26+
assets: await this.getAssets(entryKey)
27+
};
2428
}
2529

2630
return json
2731
}
2832
} satisfies StartManifest & { json(): Promise<Record<string, any>> };
2933
}
34+
35+
const CLIENT_BASE_PATH = "_build";
36+
37+
function createHtmlTagsForAssets(assets: string[]) {
38+
return assets
39+
.filter(
40+
(asset) =>
41+
asset.endsWith(".css") ||
42+
asset.endsWith(".js") ||
43+
asset.endsWith(".mjs"),
44+
)
45+
.map((asset) => ({
46+
tag: "link",
47+
attrs: {
48+
href: join("/", CLIENT_BASE_PATH, asset),
49+
key: join("/", CLIENT_BASE_PATH, asset),
50+
...(asset.endsWith(".css")
51+
? { rel: "stylesheet", fetchPriority: "high" }
52+
: { rel: "modulepreload" }),
53+
},
54+
}));
55+
}
56+
57+
function findAssetsInViteManifest(manifest: any, id: string, assetMap = new Map(), stack: string[] = []) {
58+
if (stack.includes(id)) {
59+
return [];
60+
}
61+
62+
const cached = assetMap.get(id);
63+
if (cached) {
64+
return cached;
65+
}
66+
const chunk = manifest[id];
67+
if (!chunk) {
68+
return [];
69+
}
70+
71+
const assets = [
72+
...(chunk.assets?.filter(Boolean) || []),
73+
...(chunk.css?.filter(Boolean) || [])
74+
];
75+
if (chunk.imports) {
76+
stack.push(id);
77+
for (let i = 0, l = chunk.imports.length; i < l; i++) {
78+
assets.push(...findAssetsInViteManifest(manifest, chunk.imports[i], assetMap, stack));
79+
}
80+
stack.pop();
81+
}
82+
assets.push(chunk.file);
83+
const all = Array.from(new Set(assets));
84+
assetMap.set(id, all);
85+
86+
return all;
87+
}
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import { manifest } from "solid-start:server-manifest"
21
import { getSsrDevManifest } from "./dev-server-manifest.js";
32
import { getSsrProdManifest } from "./prod-server-manifest.js";
43

5-
export function getSsrManifest(server: boolean) {
6-
return import.meta.env.DEV ? getSsrDevManifest(server, manifest.clientEntryId) : getSsrProdManifest()
4+
export function getSsrManifest(target: "client" | "server") {
5+
return import.meta.env.DEV ? getSsrDevManifest(target) : getSsrProdManifest()
76
}
87

98
export { getSsrManifest as getManifest }

packages/start/src/server/spa/StartServer.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,13 @@ export function StartServer(props: { document: Component<DocumentComponentProps>
2929
<>
3030
<script
3131
nonce={nonce}
32-
innerHTML={`window.manifest = ${JSON.stringify(manifest.clientManifestData)}`}
32+
innerHTML={`window.manifest = ${JSON.stringify(context.manifest)}`}
3333
/>
3434
<script type="module" nonce={nonce} async src={getClientEntryPath()} />
3535
</>
3636
) : (
3737
<>
38-
<script
39-
innerHTML={`window.manifest = ${JSON.stringify(manifest.clientManifestData)}`}
40-
/>
38+
<script innerHTML={`window.manifest = ${JSON.stringify(context.manifest)}`} />
4139
<script type="module" nonce={nonce} async src={getClientEntryPath()} />
4240
</>
4341
)

packages/start/src/virtual.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ declare module "solid-start:server-manifest" {
1616
interface StartServerManifest {
1717
clientEntryId: string;
1818
clientViteManifest: Record<string, { css?: Array<string>, file: string, [key: string]: unknown }>;
19-
clientManifestData: ClientManifest;
2019
}
2120

2221
export const manifest: StartServerManifest;

0 commit comments

Comments
 (0)