@solidjs/start 2.0.0-alpha.0 → 2.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/dist/client/mount.d.ts +1 -7
- package/dist/client/mount.js +1 -99
- package/dist/config/constants.js +2 -2
- package/dist/config/dev-server.js +10 -0
- package/dist/config/fs-router.js +10 -22
- package/dist/config/fs-routes/fs-watcher.js +4 -4
- package/dist/config/fs-routes/index.js +4 -6
- package/dist/config/fs-routes/router.js +10 -11
- package/dist/config/fs-routes/tree-shake.js +12 -21
- package/dist/config/index.js +42 -42
- package/dist/config/lazy.js +42 -12
- package/dist/config/manifest.js +4 -3
- package/dist/config/vite-utils.d.ts +5 -0
- package/dist/config/vite-utils.js +7 -3
- package/dist/http/index.d.ts +1 -4
- package/dist/http/index.js +3 -5
- package/dist/index.d.ts +0 -1
- package/dist/middleware/index.d.ts +5 -2
- package/dist/middleware/index.js +6 -1
- package/dist/router.jsx +2 -2
- package/dist/server/StartServer.jsx +2 -0
- package/dist/server/assets/PatchVirtualDevStyles.d.ts +4 -0
- package/dist/server/assets/PatchVirtualDevStyles.jsx +28 -0
- package/dist/server/assets/index.js +1 -1
- package/dist/server/assets/render.jsx +2 -2
- package/dist/server/collect-styles.js +9 -21
- package/dist/server/fetchEvent.spec.js +1 -1
- package/dist/server/handler.js +30 -15
- package/dist/server/index.d.ts +1 -0
- package/dist/server/manifest/dev-client-manifest.js +1 -1
- package/dist/server/manifest/dev-ssr-manifest.js +1 -1
- package/dist/server/manifest/prod-ssr-manifest.js +7 -12
- package/dist/server/routes.js +3 -3
- package/dist/server/server-fns-runtime.js +2 -2
- package/dist/server/server-functions-handler.js +6 -11
- package/dist/server/server-runtime.js +8 -8
- package/dist/server/spa/StartServer.jsx +2 -0
- package/dist/shared/dev-overlay/CodeView.d.ts +1 -1
- package/dist/shared/dev-overlay/CodeView.jsx +23 -34
- package/dist/shared/dev-overlay/DevOverlayDialog.jsx +4 -4
- package/dist/shared/dev-overlay/get-source-map.d.ts +1 -1
- package/dist/shared/dev-overlay/get-source-map.js +5 -5
- package/dist/shared/dev-overlay/icons.d.ts +10 -10
- package/dist/shared/dev-overlay/icons.jsx +91 -91
- package/dist/shared/dev-overlay/index.jsx +1 -1
- package/dist/shared/lazy.js +4 -2
- package/env.d.ts +9 -0
- package/package.json +5 -4
- package/scripts/build.js +3 -3
- package/scripts/validate-imports.js +8 -8
- package/src/client/mount.ts +1 -114
- package/src/config/constants.ts +3 -3
- package/src/config/dev-server.ts +107 -99
- package/src/config/fs-router.ts +140 -155
- package/src/config/fs-routes/fs-watcher.ts +57 -61
- package/src/config/fs-routes/index.ts +117 -119
- package/src/config/fs-routes/router.ts +12 -13
- package/src/config/fs-routes/tree-shake.ts +342 -363
- package/src/config/index.ts +42 -43
- package/src/config/lazy.ts +47 -16
- package/src/config/manifest.ts +8 -7
- package/src/config/vite-utils.ts +9 -9
- package/src/env.d.ts +10 -28
- package/src/http/index.ts +105 -142
- package/src/index.tsx +0 -12
- package/src/internal.d.ts +1 -1
- package/src/middleware/index.ts +42 -49
- package/src/router.tsx +4 -3
- package/src/server/StartServer.tsx +3 -7
- package/src/server/assets/PatchVirtualDevStyles.tsx +31 -0
- package/src/server/assets/index.ts +1 -1
- package/src/server/assets/render.tsx +6 -2
- package/src/server/collect-styles.ts +49 -73
- package/src/server/fetchEvent.spec.ts +71 -75
- package/src/server/fetchEvent.ts +17 -17
- package/src/server/handler.ts +138 -129
- package/src/server/index.tsx +13 -0
- package/src/server/manifest/client-manifest.ts +1 -1
- package/src/server/manifest/dev-client-manifest.ts +7 -5
- package/src/server/manifest/dev-ssr-manifest.ts +8 -6
- package/src/server/manifest/prod-client-manifest.ts +7 -4
- package/src/server/manifest/prod-ssr-manifest.ts +78 -94
- package/src/server/manifest/ssr-manifest.ts +4 -2
- package/src/server/routes.ts +96 -108
- package/src/server/server-fns-runtime.ts +3 -3
- package/src/server/server-functions-handler.ts +294 -319
- package/src/server/server-runtime.ts +13 -13
- package/src/server/spa/StartServer.tsx +2 -0
- package/src/server/spa/handler.ts +12 -12
- package/src/server/types.ts +46 -46
- package/src/server/util.ts +4 -4
- package/src/shared/ErrorBoundary.tsx +1 -1
- package/src/shared/HttpHeader.tsx +20 -20
- package/src/shared/HttpStatusCode.ts +14 -14
- package/src/shared/clientOnly.ts +3 -3
- package/src/shared/dev-overlay/CodeView.tsx +43 -46
- package/src/shared/dev-overlay/DevOverlayDialog.tsx +4 -4
- package/src/shared/dev-overlay/createStackFrame.ts +59 -62
- package/src/shared/dev-overlay/env.d.ts +2 -2
- package/src/shared/dev-overlay/get-source-map.ts +5 -7
- package/src/shared/dev-overlay/icons.tsx +289 -121
- package/src/shared/dev-overlay/index.tsx +1 -1
- package/src/shared/lazy.ts +4 -3
- package/src/shared/serverFunction.ts +1 -1
- package/src/virtual.d.ts +10 -10
- package/tsconfig.json +2 -2
- package/vitest.config.ts +2 -2
package/src/server/handler.ts
CHANGED
|
@@ -10,89 +10,81 @@ import { decorateHandler, decorateMiddleware } from "./fetchEvent.ts";
|
|
|
10
10
|
import { getSsrManifest } from "./manifest/ssr-manifest.ts";
|
|
11
11
|
import { matchAPIRoute } from "./routes.ts";
|
|
12
12
|
import { handleServerFunction } from "./server-functions-handler.ts";
|
|
13
|
-
import type {
|
|
14
|
-
APIEvent,
|
|
15
|
-
FetchEvent,
|
|
16
|
-
HandlerOptions,
|
|
17
|
-
PageEvent,
|
|
18
|
-
} from "./types.ts";
|
|
13
|
+
import type { APIEvent, FetchEvent, HandlerOptions, PageEvent } from "./types.ts";
|
|
19
14
|
import { getExpectedRedirectStatus } from "./util.ts";
|
|
20
15
|
|
|
21
16
|
const SERVER_FN_BASE = "/_server";
|
|
22
17
|
|
|
23
18
|
export function createBaseHandler(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
| HandlerOptions
|
|
28
|
-
| ((context: PageEvent) => HandlerOptions | Promise<HandlerOptions>) = {},
|
|
19
|
+
createPageEvent: (e: FetchEvent) => Promise<PageEvent>,
|
|
20
|
+
fn: (context: PageEvent) => JSX.Element,
|
|
21
|
+
options: HandlerOptions | ((context: PageEvent) => HandlerOptions | Promise<HandlerOptions>) = {},
|
|
29
22
|
) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
23
|
+
const handler = defineHandler({
|
|
24
|
+
middleware: middleware.length ? middleware.map(decorateMiddleware) : undefined,
|
|
25
|
+
handler: decorateHandler(async (e: H3Event) => {
|
|
26
|
+
const event = getRequestEvent()!;
|
|
27
|
+
const url = new URL(event.request.url);
|
|
28
|
+
const pathname = stripBaseUrl(url.pathname);
|
|
36
29
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const serverFnResponse = await handleServerFunction(e);
|
|
30
|
+
if (pathname.startsWith(SERVER_FN_BASE)) {
|
|
31
|
+
const serverFnResponse = await handleServerFunction(e);
|
|
40
32
|
|
|
41
33
|
if (serverFnResponse instanceof Response)
|
|
42
34
|
return produceResponseWithEventHeaders(serverFnResponse);
|
|
43
35
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
sharedConfig.context = { event };
|
|
59
|
-
const res = await fn!(event);
|
|
36
|
+
return new Response(serverFnResponse as any, {
|
|
37
|
+
headers: e.res.headers,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const match = matchAPIRoute(pathname, event.request.method);
|
|
42
|
+
if (match) {
|
|
43
|
+
const mod = await match.handler.import();
|
|
44
|
+
const fn =
|
|
45
|
+
event.request.method === "HEAD" ? mod["HEAD"] || mod["GET"] : mod[event.request.method];
|
|
46
|
+
(event as APIEvent).params = match.params || {};
|
|
47
|
+
// @ts-expect-error
|
|
48
|
+
sharedConfig.context = { event };
|
|
49
|
+
const res = await fn!(event);
|
|
60
50
|
if (res !== undefined) {
|
|
61
|
-
if(res instanceof Response) return produceResponseWithEventHeaders(res)
|
|
51
|
+
if (res instanceof Response) return produceResponseWithEventHeaders(res);
|
|
62
52
|
|
|
63
53
|
return res;
|
|
64
54
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
55
|
+
if (event.request.method !== "GET") {
|
|
56
|
+
throw new Error(
|
|
57
|
+
`API handler for ${event.request.method} "${event.request.url}" did not return a response.`,
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
if (!match.isPage) return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const context = await createPageEvent(event);
|
|
64
|
+
|
|
65
|
+
const resolvedOptions =
|
|
66
|
+
typeof options === "function" ? await options(context) : { ...options };
|
|
67
|
+
const mode = resolvedOptions.mode || "stream";
|
|
68
|
+
if (resolvedOptions.nonce) context.nonce = resolvedOptions.nonce;
|
|
69
|
+
|
|
70
|
+
if (mode === "sync" || !import.meta.env.START_SSR) {
|
|
71
|
+
const html = renderToString(() => {
|
|
72
|
+
(sharedConfig.context as any).event = context;
|
|
73
|
+
return fn(context);
|
|
74
|
+
}, resolvedOptions);
|
|
75
|
+
context.complete = true;
|
|
76
|
+
|
|
77
|
+
if (context.response && context.response.headers.get("Location")) {
|
|
88
78
|
const status = getExpectedRedirectStatus(context.response);
|
|
89
79
|
return redirect(context.response.headers.get("Location")!, status);
|
|
90
80
|
}
|
|
91
81
|
|
|
92
|
-
|
|
93
|
-
|
|
82
|
+
event.response.headers.set("content-type", "text/html");
|
|
83
|
+
|
|
84
|
+
return html;
|
|
85
|
+
}
|
|
94
86
|
|
|
95
|
-
|
|
87
|
+
if (resolvedOptions.onCompleteAll) {
|
|
96
88
|
const og = resolvedOptions.onCompleteAll;
|
|
97
89
|
resolvedOptions.onCompleteAll = options => {
|
|
98
90
|
handleStreamCompleteRedirect(context)(options);
|
|
@@ -107,10 +99,10 @@ export function createBaseHandler(
|
|
|
107
99
|
};
|
|
108
100
|
} else resolvedOptions.onCompleteShell = handleShellCompleteRedirect(context, e);
|
|
109
101
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
102
|
+
const _stream = renderToStream(() => {
|
|
103
|
+
(sharedConfig.context as any).event = context;
|
|
104
|
+
return fn(context);
|
|
105
|
+
}, resolvedOptions);
|
|
114
106
|
const stream = _stream as typeof _stream & PromiseLike<string>; // stream has a hidden 'then' method
|
|
115
107
|
|
|
116
108
|
if (context.response && context.response.headers.get("Location")) {
|
|
@@ -118,48 +110,46 @@ export function createBaseHandler(
|
|
|
118
110
|
return redirect(context.response.headers.get("Location")!, status);
|
|
119
111
|
}
|
|
120
112
|
|
|
121
|
-
|
|
113
|
+
if (mode === "async") return await stream;
|
|
122
114
|
|
|
123
115
|
delete (stream as any).then;
|
|
124
116
|
|
|
125
117
|
// using TransformStream in dev can cause solid-start-dev-server to crash
|
|
126
118
|
// when stream is cancelled
|
|
127
|
-
if(globalThis.USING_SOLID_START_DEV_SERVER) return stream
|
|
119
|
+
if (globalThis.USING_SOLID_START_DEV_SERVER) return stream;
|
|
128
120
|
|
|
129
121
|
// returning stream directly breaks cloudflare workers
|
|
130
122
|
const { writable, readable } = new TransformStream();
|
|
131
123
|
stream.pipeTo(writable);
|
|
132
|
-
return readable
|
|
133
|
-
|
|
134
|
-
|
|
124
|
+
return readable;
|
|
125
|
+
}),
|
|
126
|
+
});
|
|
135
127
|
|
|
136
|
-
|
|
128
|
+
const app = new H3();
|
|
137
129
|
|
|
138
130
|
app.use(handler);
|
|
139
131
|
|
|
140
|
-
|
|
132
|
+
return app;
|
|
141
133
|
}
|
|
142
134
|
|
|
143
135
|
export function createHandler(
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
| HandlerOptions
|
|
147
|
-
| ((context: PageEvent) => HandlerOptions | Promise<HandlerOptions>) = {},
|
|
136
|
+
fn: (context: PageEvent) => JSX.Element,
|
|
137
|
+
options: HandlerOptions | ((context: PageEvent) => HandlerOptions | Promise<HandlerOptions>) = {},
|
|
148
138
|
) {
|
|
149
|
-
|
|
139
|
+
return createBaseHandler(createPageEvent, fn, options);
|
|
150
140
|
}
|
|
151
141
|
|
|
152
142
|
export async function createPageEvent(ctx: FetchEvent) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
143
|
+
ctx.response.headers.set("Content-Type", "text/html");
|
|
144
|
+
// const prevPath = ctx.request.headers.get("x-solid-referrer");
|
|
145
|
+
// const mutation = ctx.request.headers.get("x-solid-mutation") === "true";
|
|
146
|
+
const manifest = getSsrManifest(import.meta.env.SSR && import.meta.env.DEV ? "ssr" : "client");
|
|
157
147
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
148
|
+
// Handle Vite build.cssCodeSplit
|
|
149
|
+
// When build.cssCodeSplit is false, a single CSS file is generated with the key style.css
|
|
150
|
+
const mergedCSS = import.meta.env.PROD ? await manifest.getAssets("style.css") : [];
|
|
161
151
|
|
|
162
|
-
|
|
152
|
+
const assets = [
|
|
163
153
|
...mergedCSS,
|
|
164
154
|
...(await manifest.getAssets(import.meta.env.START_CLIENT_ENTRY)),
|
|
165
155
|
...(await manifest.getAssets(import.meta.env.START_APP_ENTRY)),
|
|
@@ -169,52 +159,49 @@ export async function createPageEvent(ctx: FetchEvent) {
|
|
|
169
159
|
// )
|
|
170
160
|
// : [])
|
|
171
161
|
];
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
162
|
+
const pageEvent: PageEvent = Object.assign(ctx, {
|
|
163
|
+
assets,
|
|
164
|
+
router: {
|
|
165
|
+
submission: initFromFlash(ctx) as any,
|
|
166
|
+
},
|
|
167
|
+
routes: createRoutes(),
|
|
168
|
+
// prevUrl: prevPath || "",
|
|
169
|
+
// mutation: mutation,
|
|
170
|
+
// $type: FETCH_EVENT,
|
|
171
|
+
complete: false,
|
|
172
|
+
$islands: new Set<string>(),
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
return pageEvent;
|
|
186
176
|
}
|
|
187
177
|
|
|
188
178
|
function initFromFlash(ctx: FetchEvent) {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
} finally {
|
|
209
|
-
setCookie(ctx.nativeEvent, "flash", "", { maxAge: 0 });
|
|
210
|
-
}
|
|
179
|
+
const flash = getCookie(ctx.nativeEvent, "flash");
|
|
180
|
+
if (!flash) return;
|
|
181
|
+
try {
|
|
182
|
+
const param = JSON.parse(flash);
|
|
183
|
+
if (!param || !param.result) return;
|
|
184
|
+
const input = [...param.input.slice(0, -1), new Map(param.input[param.input.length - 1])];
|
|
185
|
+
const result = param.error ? new Error(param.result) : param.result;
|
|
186
|
+
return {
|
|
187
|
+
input,
|
|
188
|
+
url: param.url,
|
|
189
|
+
pending: false,
|
|
190
|
+
result: param.thrown ? undefined : result,
|
|
191
|
+
error: param.thrown ? result : undefined,
|
|
192
|
+
};
|
|
193
|
+
} catch (e) {
|
|
194
|
+
console.error(e);
|
|
195
|
+
} finally {
|
|
196
|
+
setCookie(ctx.nativeEvent, "flash", "", { maxAge: 0 });
|
|
197
|
+
}
|
|
211
198
|
}
|
|
212
199
|
|
|
213
200
|
function handleShellCompleteRedirect(context: PageEvent, e: H3Event) {
|
|
214
201
|
return () => {
|
|
215
202
|
if (context.response && context.response.headers.get("Location")) {
|
|
216
203
|
const status = getExpectedRedirectStatus(context.response);
|
|
217
|
-
e.res.status = status
|
|
204
|
+
e.res.status = status;
|
|
218
205
|
e.res.headers.set("Location", context.response.headers.get("Location")!);
|
|
219
206
|
}
|
|
220
207
|
};
|
|
@@ -234,17 +221,39 @@ function produceResponseWithEventHeaders(res: Response) {
|
|
|
234
221
|
let ret = res;
|
|
235
222
|
|
|
236
223
|
// Response.redirect returns an immutable value, so we clone on any redirect just in case
|
|
237
|
-
if(300 <= res.status && res.status < 400) {
|
|
224
|
+
if (300 <= res.status && res.status < 400) {
|
|
225
|
+
const cookies = res.headers.getSetCookie?.() ?? [];
|
|
226
|
+
const headers = new Headers();
|
|
227
|
+
res.headers.forEach((value, key) => {
|
|
228
|
+
if (key.toLowerCase() !== "set-cookie") {
|
|
229
|
+
headers.set(key, value);
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
for (const cookie of cookies) {
|
|
233
|
+
headers.append("Set-Cookie", cookie);
|
|
234
|
+
}
|
|
238
235
|
ret = new Response(res.body, {
|
|
239
236
|
status: res.status,
|
|
240
237
|
statusText: res.statusText,
|
|
241
|
-
headers
|
|
238
|
+
headers,
|
|
242
239
|
});
|
|
243
240
|
}
|
|
244
241
|
|
|
245
|
-
|
|
246
|
-
|
|
242
|
+
const eventCookies = event.response.headers.getSetCookie?.() ?? [];
|
|
243
|
+
for (const cookie of eventCookies) {
|
|
244
|
+
ret.headers.append("Set-Cookie", cookie);
|
|
247
245
|
}
|
|
248
246
|
|
|
249
|
-
|
|
247
|
+
for (const [name, value] of event.response.headers) {
|
|
248
|
+
if (name.toLowerCase() !== "set-cookie") {
|
|
249
|
+
ret.headers.set(name, value);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return ret;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function stripBaseUrl(path: string) {
|
|
257
|
+
if (import.meta.env.BASE_URL === "/" || import.meta.env.BASE_URL === "") return path;
|
|
258
|
+
return path.slice(import.meta.env.BASE_URL.length);
|
|
250
259
|
}
|
package/src/server/index.tsx
CHANGED
|
@@ -3,6 +3,19 @@ export { getServerFunctionMeta } from "../shared/serverFunction.ts";
|
|
|
3
3
|
export { StartServer } from "./StartServer.tsx";
|
|
4
4
|
export { createHandler } from "./handler.ts";
|
|
5
5
|
|
|
6
|
+
export type {
|
|
7
|
+
APIEvent,
|
|
8
|
+
APIHandler,
|
|
9
|
+
Asset,
|
|
10
|
+
ContextMatches,
|
|
11
|
+
DocumentComponentProps,
|
|
12
|
+
FetchEvent,
|
|
13
|
+
HandlerOptions,
|
|
14
|
+
PageEvent,
|
|
15
|
+
ResponseStub,
|
|
16
|
+
ServerFunctionMeta,
|
|
17
|
+
} from "./types.ts";
|
|
18
|
+
|
|
6
19
|
/**
|
|
7
20
|
* Checks if user has set a redirect status in the response.
|
|
8
21
|
* If not, falls back to the 302 (temporary redirect)
|
|
@@ -2,7 +2,7 @@ import { getClientDevManifest } from "./dev-client-manifest.ts";
|
|
|
2
2
|
import { getClientProdManifest } from "./prod-client-manifest.ts";
|
|
3
3
|
|
|
4
4
|
export function getClientManifest() {
|
|
5
|
-
|
|
5
|
+
return import.meta.env.DEV ? getClientDevManifest() : getClientProdManifest();
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
export { getClientManifest as getManifest };
|
|
@@ -3,17 +3,19 @@ import { join } from "pathe";
|
|
|
3
3
|
export function getClientDevManifest() {
|
|
4
4
|
return {
|
|
5
5
|
import(id) {
|
|
6
|
-
return import(/* @vite-ignore */ join("/", id))
|
|
6
|
+
return import(/* @vite-ignore */ join("/", id));
|
|
7
7
|
},
|
|
8
8
|
async getAssets(id) {
|
|
9
9
|
const assetsPath = `/@manifest/client/${Date.now()}/assets?id=${id}`;
|
|
10
10
|
|
|
11
11
|
const assets = (await import(/* @vite-ignore */ assetsPath)).default;
|
|
12
12
|
|
|
13
|
-
return await Promise.all(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
return await Promise.all(
|
|
14
|
+
assets.map(async (v: any) => ({
|
|
15
|
+
...v,
|
|
16
|
+
children: await v.children(),
|
|
17
|
+
})),
|
|
18
|
+
);
|
|
17
19
|
},
|
|
18
20
|
} satisfies StartManifest & { import(id: string): Promise<any> };
|
|
19
21
|
}
|
|
@@ -8,14 +8,16 @@ export function getSsrDevManifest(environment: "client" | "ssr") {
|
|
|
8
8
|
|
|
9
9
|
const assets = (await import(/* @vite-ignore */ assetsPath)).default;
|
|
10
10
|
|
|
11
|
-
return await Promise.all(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
return await Promise.all(
|
|
12
|
+
assets.map(async (v: any) => ({
|
|
13
|
+
...v,
|
|
14
|
+
children: await v.children(),
|
|
15
|
+
})),
|
|
16
|
+
);
|
|
15
17
|
},
|
|
16
18
|
} satisfies StartManifest & {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
path(id: string): string;
|
|
20
|
+
};
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
export { getSsrDevManifest as getSsrManifest };
|
|
@@ -2,17 +2,20 @@ export function getClientProdManifest() {
|
|
|
2
2
|
return {
|
|
3
3
|
import(id) {
|
|
4
4
|
// @ts-ignore
|
|
5
|
-
return import(/* @vite-ignore */ window.manifest[id].output)
|
|
5
|
+
return import(/* @vite-ignore */ window.manifest[id].output);
|
|
6
6
|
},
|
|
7
7
|
async getAssets(id) {
|
|
8
8
|
if (id.startsWith("./")) id = id.slice(2);
|
|
9
9
|
|
|
10
10
|
// @ts-ignore
|
|
11
|
-
return window.manifest[id]?.assets ?? []
|
|
11
|
+
return window.manifest[id]?.assets ?? [];
|
|
12
12
|
},
|
|
13
13
|
async json() {
|
|
14
14
|
// @ts-ignore
|
|
15
|
-
return window.manifest
|
|
15
|
+
return window.manifest;
|
|
16
16
|
},
|
|
17
|
-
} satisfies StartManifest & {
|
|
17
|
+
} satisfies StartManifest & {
|
|
18
|
+
json(): Promise<Record<string, any>>;
|
|
19
|
+
import(id: string): Promise<any>;
|
|
20
|
+
};
|
|
18
21
|
}
|
|
@@ -5,121 +5,105 @@ import type { Asset } from "../assets/render.tsx";
|
|
|
5
5
|
|
|
6
6
|
// Only reads from client manifest atm, might need server support for islands
|
|
7
7
|
export function getSsrProdManifest() {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
const viteManifest = clientViteManifest;
|
|
9
|
+
return {
|
|
10
|
+
path(id: string) {
|
|
11
11
|
if (id.startsWith("./")) id = id.slice(2);
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
if (!viteManifestEntry)
|
|
16
|
-
throw new Error(`No entry found in vite manifest for '${id}'`);
|
|
13
|
+
const viteManifestEntry = clientViteManifest[id /*import.meta.env.START_CLIENT_ENTRY*/];
|
|
14
|
+
if (!viteManifestEntry) throw new Error(`No entry found in vite manifest for '${id}'`);
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
return join("/", viteManifestEntry.file);
|
|
17
|
+
},
|
|
18
|
+
async getAssets(id) {
|
|
21
19
|
if (id.startsWith("./")) id = id.slice(2);
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
async json() {
|
|
28
|
-
const json: Record<string, any> = {};
|
|
21
|
+
return createHtmlTagsForAssets(findAssetsInViteManifest(clientViteManifest, id));
|
|
22
|
+
},
|
|
23
|
+
async json() {
|
|
24
|
+
const json: Record<string, any> = {};
|
|
29
25
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
const entryKeys = Object.keys(viteManifest)
|
|
27
|
+
.filter(id => viteManifest[id]?.isEntry || viteManifest[id]?.isDynamicEntry)
|
|
28
|
+
.map(id => id);
|
|
33
29
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
30
|
+
for (const entryKey of entryKeys) {
|
|
31
|
+
json[entryKey] = {
|
|
32
|
+
output: join("/", viteManifest[entryKey]!.file),
|
|
33
|
+
assets: await this.getAssets(entryKey),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
40
36
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
37
|
+
return json;
|
|
38
|
+
},
|
|
39
|
+
} satisfies StartManifest & {
|
|
40
|
+
json(): Promise<Record<string, any>>;
|
|
41
|
+
path(id: string): string;
|
|
42
|
+
};
|
|
47
43
|
}
|
|
48
44
|
|
|
49
45
|
function createHtmlTagsForAssets(assets: string[]) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
},
|
|
67
|
-
}));
|
|
46
|
+
return assets
|
|
47
|
+
.filter(
|
|
48
|
+
asset =>
|
|
49
|
+
asset.endsWith(".css") ||
|
|
50
|
+
asset.endsWith(".js") ||
|
|
51
|
+
asset.endsWith(".ts") ||
|
|
52
|
+
asset.endsWith(".mjs"),
|
|
53
|
+
)
|
|
54
|
+
.map<Asset>(asset => ({
|
|
55
|
+
tag: "link",
|
|
56
|
+
attrs: {
|
|
57
|
+
href: "/" + asset,
|
|
58
|
+
key: asset,
|
|
59
|
+
...(asset.endsWith(".css") ? { rel: "stylesheet" } : { rel: "modulepreload" }),
|
|
60
|
+
},
|
|
61
|
+
}));
|
|
68
62
|
}
|
|
69
63
|
|
|
70
64
|
const entryId = import.meta.env.START_CLIENT_ENTRY.slice(2);
|
|
71
65
|
let entryImports: string[] | undefined = undefined;
|
|
72
66
|
|
|
73
67
|
function findAssetsInViteManifest(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
68
|
+
manifest: Manifest,
|
|
69
|
+
id: string,
|
|
70
|
+
assetMap = new Map(),
|
|
71
|
+
stack: string[] = [],
|
|
78
72
|
) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
73
|
+
if (stack.includes(id)) {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
82
76
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
77
|
+
const cached = assetMap.get(id);
|
|
78
|
+
if (cached) {
|
|
79
|
+
return cached;
|
|
80
|
+
}
|
|
81
|
+
const chunk = manifest[id];
|
|
82
|
+
if (!chunk) {
|
|
83
|
+
return [];
|
|
84
|
+
}
|
|
91
85
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
...(manifest[entryId]?.imports ?? [])
|
|
96
|
-
];
|
|
97
|
-
}
|
|
86
|
+
if (!entryImports) {
|
|
87
|
+
entryImports = [entryId, ...(manifest[entryId]?.imports ?? [])];
|
|
88
|
+
}
|
|
98
89
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
90
|
+
// Only include entry imports, if we are specifically crawling the entry
|
|
91
|
+
// Chunks (e.g. routes) that import something from entry, should not render entry css redundantly
|
|
92
|
+
const excludeEntryImports = id !== entryId;
|
|
102
93
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
stack.pop();
|
|
119
|
-
}
|
|
120
|
-
assets.push(chunk.file);
|
|
121
|
-
const all = Array.from(new Set(assets));
|
|
122
|
-
assetMap.set(id, all);
|
|
94
|
+
const assets = chunk.css?.filter(Boolean) || [];
|
|
95
|
+
if (chunk.imports) {
|
|
96
|
+
stack.push(id);
|
|
97
|
+
for (let i = 0, l = chunk.imports.length; i < l; i++) {
|
|
98
|
+
const importId = chunk.imports[i];
|
|
99
|
+
if (!importId || (excludeEntryImports && entryImports.includes(importId))) continue;
|
|
100
|
+
assets.push(...findAssetsInViteManifest(manifest, importId, assetMap, stack));
|
|
101
|
+
}
|
|
102
|
+
stack.pop();
|
|
103
|
+
}
|
|
104
|
+
assets.push(chunk.file);
|
|
105
|
+
const all = Array.from(new Set(assets));
|
|
106
|
+
assetMap.set(id, all);
|
|
123
107
|
|
|
124
|
-
|
|
108
|
+
return all;
|
|
125
109
|
}
|