vike-lite 1.8.1 → 1.9.0

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.
@@ -1,4 +1,4 @@
1
- import { t as Config } from "../index-Dt5n1zWh.mjs";
1
+ import { t as Config } from "../index-ZDN-jKX_.mjs";
2
2
 
3
3
  //#region src/server/store.d.ts
4
4
  interface VikeState {
@@ -1,2 +1,2 @@
1
- import { n as RenderContext, r as matchRoute, t as Config } from "../index-Dt5n1zWh.mjs";
1
+ import { n as RenderContext, r as matchRoute, t as Config } from "../index-ZDN-jKX_.mjs";
2
2
  export { Config, RenderContext, matchRoute };
@@ -10,8 +10,7 @@ function navigate(url, options) {
10
10
  let finalUrl = url;
11
11
  if (finalUrl.startsWith("/")) finalUrl = (BASE_URL.endsWith("/") ? BASE_URL.slice(0, -1) : BASE_URL) + (finalUrl === "/" ? "" : finalUrl);
12
12
  globalThis.history.pushState(null, "", finalUrl);
13
- globalThis.dispatchEvent(new Event("popstate"));
14
- if (!options?.keepScrollPosition) globalThis.scrollTo(0, 0);
13
+ globalThis.dispatchEvent(new CustomEvent("vike-navigate", { detail: { keepScrollPosition: options?.keepScrollPosition } }));
15
14
  }
16
15
  //#endregion
17
16
  export { navigate };
@@ -17,6 +17,7 @@ interface RenderContext {
17
17
  jsPreloads: string;
18
18
  entryClient: string;
19
19
  };
20
+ nonce?: string;
20
21
  }
21
22
  type Config = {
22
23
  onRenderHtml: () => Promise<{
package/dist/index.d.mts CHANGED
@@ -5,6 +5,7 @@ type PageContext<Data = unknown> = {
5
5
  urlPathname: string;
6
6
  data?: Data;
7
7
  title?: string;
8
+ nonce?: string;
8
9
  is404?: boolean;
9
10
  is500?: boolean;
10
11
  errorMessage?: string;
package/dist/server.d.mts CHANGED
@@ -1,4 +1,8 @@
1
1
  //#region src/server/renderPage.d.ts
2
- declare function renderPage(req: Request): Promise<Response>;
2
+ declare function renderPage(req: Request, {
3
+ nonce
4
+ }: {
5
+ nonce?: string;
6
+ }): Promise<Response>;
3
7
  //#endregion
4
8
  export { renderPage };
package/dist/server.mjs CHANGED
@@ -20,37 +20,42 @@ const isProd = process.env.NODE_ENV === "production";
20
20
  function withBase(file) {
21
21
  return `${BASE_URL.replace(/\/$/, "")}/${file.replace(/^\//, "")}`;
22
22
  }
23
- function getAssets(route) {
23
+ function getAssets(route, nonce) {
24
24
  if (!isProd) return {
25
25
  cssLinks: "",
26
26
  jsPreloads: "",
27
27
  entryClient: withBase("@id/virtual:entry-client")
28
28
  };
29
29
  const cssFiles = /* @__PURE__ */ new Set();
30
- const jsFiles = /* @__PURE__ */ new Set();
31
- const visitedKeys = /* @__PURE__ */ new Set();
30
+ const jsFiles = /* @__PURE__ */ new Map();
32
31
  const { manifest } = store;
33
32
  function getVirtualEntryClientKey() {
34
33
  for (const key in manifest) if (manifest[key].isEntry) return key;
35
34
  throw new Error("entry-client not found in manifest");
36
35
  }
37
- function collectAssets(key) {
38
- if (visitedKeys.has(key)) return;
39
- visitedKeys.add(key);
36
+ function collectAssets(key, isCritical) {
40
37
  const chunk = manifest[key];
41
- jsFiles.add(chunk.file);
38
+ if (!chunk) return;
39
+ const current = jsFiles.get(chunk.file);
40
+ if (current === true) return;
41
+ if (current === false && !isCritical) return;
42
+ jsFiles.set(chunk.file, isCritical);
42
43
  if (chunk.css) for (const css of chunk.css) cssFiles.add(css);
43
- if (chunk.imports) for (const imp of chunk.imports) collectAssets(imp);
44
+ if (chunk.imports) for (const imp of chunk.imports) collectAssets(imp, false);
44
45
  }
45
46
  const virtualEntryClientKey = getVirtualEntryClientKey();
46
- collectAssets(virtualEntryClientKey);
47
+ collectAssets(virtualEntryClientKey, true);
47
48
  const { page, layout, head } = route;
48
- collectAssets(page);
49
- if (head) collectAssets(head);
50
- if (layout) collectAssets(layout);
49
+ collectAssets(page, true);
50
+ if (head) collectAssets(head, true);
51
+ if (layout) collectAssets(layout, true);
52
+ const criticalJs = [];
53
+ const sharedJs = [];
54
+ for (const [file, isCritical] of jsFiles) (isCritical ? criticalJs : sharedJs).push(file);
55
+ const nonceAttr = nonce ? ` nonce="${nonce}"` : "";
51
56
  return {
52
- cssLinks: [...cssFiles].map((href) => `<link rel="stylesheet" href="${withBase(href)}">`).join(""),
53
- jsPreloads: [...jsFiles].map((href) => `<link rel="modulepreload" href="${withBase(href)}">`).join(""),
57
+ cssLinks: [...cssFiles].map((href) => `<link rel="stylesheet" href="${withBase(href)}"${nonceAttr}>`).join(""),
58
+ jsPreloads: [...criticalJs.map((href) => `<link rel="modulepreload" href="${withBase(href)}" crossorigin fetchpriority="high"${nonceAttr}>`), ...sharedJs.map((href) => `<link rel="modulepreload" href="${withBase(href)}" crossorigin${nonceAttr}>`)].join(""),
54
59
  entryClient: withBase(manifest[virtualEntryClientKey].file)
55
60
  };
56
61
  }
@@ -91,7 +96,7 @@ async function buildPageContext(urlPathname, urlOriginal, isJsonRequest) {
91
96
  LayoutModule
92
97
  };
93
98
  }
94
- async function renderErrorPage(req, status, urlPathname, error) {
99
+ async function renderErrorPage(req, status, urlPathname, error, nonce) {
95
100
  if (!store.errorRoute) return new Response(status === 404 ? "Not Found" : "Internal Server Error", { status });
96
101
  try {
97
102
  const { default: onRenderHtml } = await store.config.onRenderHtml();
@@ -115,7 +120,8 @@ async function renderErrorPage(req, status, urlPathname, error) {
115
120
  Head: HeadModule ? HeadModule.Head ?? HeadModule.default : void 0,
116
121
  pageTitleTag: `<title>${status === 404 ? "Page Not Found" : "Server Error"}</title>`,
117
122
  serializedContext: serializeContext(pageContext),
118
- assets: getAssets(store.errorRoute)
123
+ assets: getAssets(store.errorRoute, nonce),
124
+ nonce
119
125
  });
120
126
  return new Response(html, {
121
127
  status,
@@ -126,7 +132,7 @@ async function renderErrorPage(req, status, urlPathname, error) {
126
132
  return new Response(status === 404 ? "Not Found" : "Internal Server Error", { status });
127
133
  }
128
134
  }
129
- async function renderPage(req) {
135
+ async function renderPage(req, { nonce }) {
130
136
  let { pathname } = new URL(req.url);
131
137
  if (BASE_URL !== "/") {
132
138
  const baseSlashed = BASE_URL.endsWith("/") ? BASE_URL : BASE_URL + "/";
@@ -143,7 +149,7 @@ async function renderPage(req) {
143
149
  const resolved = await buildPageContext(targetPathname, req.url, isJsonRequest);
144
150
  if (!resolved) {
145
151
  if (isJsonRequest) return Response.json({ is404: true }, { status: 404 });
146
- return renderErrorPage(req, 404, targetPathname);
152
+ return renderErrorPage(req, 404, targetPathname, nonce);
147
153
  }
148
154
  const { pageContext, route, PageModule, HeadModule, LayoutModule } = resolved;
149
155
  if (isJsonRequest) return Response.json(pageContext);
@@ -155,7 +161,8 @@ async function renderPage(req) {
155
161
  Layout: LayoutModule ? LayoutModule.Layout ?? LayoutModule.default : void 0,
156
162
  pageTitleTag: pageContext.title ? `<title>${pageContext.title}</title>` : "",
157
163
  serializedContext: serializeContext(pageContext),
158
- assets: getAssets(route)
164
+ assets: getAssets(route, nonce),
165
+ nonce
159
166
  });
160
167
  return new Response(html, {
161
168
  status: 200,
@@ -178,11 +185,11 @@ async function renderPage(req) {
178
185
  isError: true,
179
186
  reason: error.reason
180
187
  }, { status: error.statusCode });
181
- return renderErrorPage(req, error.statusCode, targetPathname, error.reason);
188
+ return renderErrorPage(req, error.statusCode, targetPathname, error.reason, nonce);
182
189
  }
183
190
  console.error("Render Error:", error);
184
191
  if (isJsonRequest) return Response.json({ is500: true }, { status: 500 });
185
- return renderErrorPage(req, 500, targetPathname, error);
192
+ return renderErrorPage(req, 500, targetPathname, error, nonce);
186
193
  }
187
194
  }
188
195
  //#endregion
package/dist/vite.mjs CHANGED
@@ -135,12 +135,45 @@ function routerPlugin({ pagesDir = "pages", serverEntry = "server/index", apiPre
135
135
  input: virtualEntryClientId,
136
136
  output: {
137
137
  format: "esm",
138
+ hoistTransitiveImports: false,
138
139
  entryFileNames: "assets/[name].[hash].js",
139
140
  chunkFileNames: (chunkInfo) => {
140
141
  if (chunkInfo.facadeModuleId?.includes(`/${pagesDir}/`)) return "assets/pages/[name].[hash].js";
141
142
  return "assets/chunks/[name].[hash].js";
142
143
  },
143
- assetFileNames: "assets/static/[name].[hash][extname]"
144
+ assetFileNames: "assets/static/[name].[hash][extname]",
145
+ codeSplitting: { groups: [
146
+ {
147
+ name: "framework",
148
+ test: /[\\/]vike-lite(?:-\w+)?[\\/]|[\\/](?:solid-js|@solidjs)[\\/]|^\0virtual:vike-lite/,
149
+ priority: 30
150
+ },
151
+ {
152
+ name: "vendor",
153
+ test(moduleId) {
154
+ if (/[\\/](node_modules|\.yarn)[\\/]/.test(moduleId)) return true;
155
+ return !moduleId.startsWith("\0") && !moduleId.startsWith(viteConfigRoot);
156
+ },
157
+ priority: 20,
158
+ minSize: 2e4
159
+ },
160
+ {
161
+ name(moduleId) {
162
+ const match = moduleId.match(new RegExp(String.raw`[\\/]${pagesDir}[\\/]([^\\/]+)[\\/]`));
163
+ return match ? `page-${match[1]}` : "shared";
164
+ },
165
+ test: new RegExp(String.raw`[\\/]${pagesDir}[\\/]`),
166
+ priority: 10
167
+ },
168
+ {
169
+ name(moduleId) {
170
+ const match = moduleId.match(new RegExp(String.raw`[\\/]${pagesDir}[\\/]([^\\/]+)[\\/]`));
171
+ return match ? `css-${match[1]}` : "css-shared";
172
+ },
173
+ test: /\.css$/,
174
+ priority: 5
175
+ }
176
+ ] }
144
177
  }
145
178
  }
146
179
  } },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vike-lite",
3
- "version": "1.8.1",
3
+ "version": "1.9.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "module": "./dist/index.mjs",