vike-lite 1.6.1 → 1.7.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.
package/README.md CHANGED
@@ -18,9 +18,10 @@ import vikeLite from 'vike-lite/vite'
18
18
  export default {
19
19
  plugins: [
20
20
  vikeLite({
21
- pagesDir = 'pages', // default
22
- serverEntry = 'server/index', // default
23
- apiPrefix = '/api' // default
21
+ pagesDir = 'pages', // Default
22
+ serverEntry = 'server/index', // Default
23
+ apiPrefix = '/api', // Default
24
+ prerender = false // Default
24
25
  })
25
26
  ]
26
27
  } satisfies UserConfig
@@ -2,8 +2,8 @@ import { t as Config } from "../index-Dt5n1zWh.mjs";
2
2
 
3
3
  //#region src/server/store.d.ts
4
4
  interface VikeState {
5
- routes: any[];
6
- errorRoute: any | null;
5
+ routes: typeof import('virtual:routes')['routes'];
6
+ errorRoute: typeof import('virtual:routes')['errorRoute'] | null;
7
7
  config: Config | null;
8
8
  manifest: Manifest | undefined;
9
9
  }
package/dist/server.mjs CHANGED
@@ -74,8 +74,8 @@ async function buildPageContext(urlPathname, urlOriginal, isJsonRequest) {
74
74
  urlPathname
75
75
  };
76
76
  const [dataMod, titleMod, PageModule, HeadModule, LayoutModule] = await Promise.all([
77
- route.data?.() ?? null,
78
- route.title?.() ?? null,
77
+ route.Data?.() ?? null,
78
+ route.Title?.() ?? null,
79
79
  isJsonRequest ? null : route.Page(),
80
80
  isJsonRequest ? null : route.Head?.() ?? null,
81
81
  isJsonRequest ? null : route.Layout?.() ?? null
@@ -137,7 +137,7 @@ async function renderErrorPage(req, status, urlPathname, error) {
137
137
  }
138
138
  }
139
139
  async function renderPage(req) {
140
- let pathname = new URL(req.url).pathname;
140
+ let { pathname } = new URL(req.url);
141
141
  if (BASE_URL !== "/") {
142
142
  const baseSlashed = BASE_URL.endsWith("/") ? BASE_URL : BASE_URL + "/";
143
143
  const baseNoSlash = baseSlashed.slice(0, -1);
package/dist/vite.d.mts CHANGED
@@ -4,7 +4,8 @@ import { Plugin } from "vite";
4
4
  declare function routerPlugin({
5
5
  pagesDir,
6
6
  serverEntry,
7
- apiPrefix
7
+ apiPrefix,
8
+ prerender
8
9
  }?: {
9
10
  /**
10
11
  * The directory where your page components are located.
@@ -24,6 +25,11 @@ declare function routerPlugin({
24
25
  * @default '/api'
25
26
  */
26
27
  apiPrefix?: string;
28
+ /**
29
+ * Whether to prerender the pages.
30
+ * @default false
31
+ */
32
+ prerender?: boolean;
27
33
  }): Plugin;
28
34
  //#endregion
29
35
  export { routerPlugin as default };
package/dist/vite.mjs CHANGED
@@ -23,16 +23,16 @@ function generateRoutes(viteRoot, pagesDir) {
23
23
  const currentHead = headFile ? `${importPath}/${headFile}` : parentHead;
24
24
  const pageFile = findFile(files, "+Page", pageExtensionsX);
25
25
  if (pageFile) {
26
- const dataFile = findFile(files, "+data", pageExtensions);
27
- const titleFile = findFile(files, "+title", pageExtensions);
28
26
  const route = {
29
27
  path: routePath || "/",
30
- page: `${importPath}/${pageFile}`,
31
- hasData: dataFile !== void 0,
32
- hasTitle: titleFile !== void 0
28
+ page: `${importPath}/${pageFile}`
33
29
  };
30
+ const dataFile = findFile(files, "+data", pageExtensions);
31
+ const titleFile = findFile(files, "+title", pageExtensions);
32
+ const prerenderFile = findFile(files, "+prerender", pageExtensions);
34
33
  if (dataFile) route.data = `${importPath}/${dataFile}`;
35
34
  if (titleFile) route.title = `${importPath}/${titleFile}`;
35
+ if (prerenderFile) route.prerender = `${importPath}/${prerenderFile}`;
36
36
  if (currentLayout) route.layout = currentLayout;
37
37
  if (currentHead) route.head = currentHead;
38
38
  routes.push(route);
@@ -98,7 +98,7 @@ async function injectFOUCStyles(server, html) {
98
98
  const SUPPORTED_RENDERERS = ["solid"];
99
99
  //#endregion
100
100
  //#region src/vite-plugin.ts
101
- function routerPlugin({ pagesDir = "pages", serverEntry = "server/index", apiPrefix = "/api" } = {}) {
101
+ function routerPlugin({ pagesDir = "pages", serverEntry = "server/index", apiPrefix = "/api", prerender = false } = {}) {
102
102
  const isProd = process.env.NODE_ENV === "production";
103
103
  let viteConfigRoot;
104
104
  let outDir;
@@ -185,10 +185,13 @@ function routerPlugin({ pagesDir = "pages", serverEntry = "server/index", apiPre
185
185
  code += `{path:'${r.path}',page:'${r.page}',Page:()=>import('/${r.page}'),`;
186
186
  if (r.head) code += `head:'${r.head}',Head:()=>import('/${r.head}'),`;
187
187
  if (r.layout) code += `layout:'${r.layout}',Layout:()=>import('/${r.layout}'),`;
188
- code += `hasData:${r.hasData},hasTitle:${r.hasTitle},`;
188
+ if (r.data) code += `data:'${r.data}',`;
189
+ if (r.title) code += `title:'${r.title}',`;
190
+ if (r.prerender) code += `prerender:'${r.prerender}',`;
189
191
  if (isSSR) {
190
- if (r.hasData) code += `data:()=>import('/${r.data}'),`;
191
- if (r.hasTitle) code += `title:()=>import('/${r.title}'),`;
192
+ if (r.data) code += `Data:()=>import('/${r.data}'),`;
193
+ if (r.title) code += `Title:()=>import('/${r.title}'),`;
194
+ if (r.prerender) code += `Prerender:()=>import('/${r.prerender}'),`;
192
195
  }
193
196
  code += "},";
194
197
  }
@@ -233,11 +236,8 @@ function routerPlugin({ pagesDir = "pages", serverEntry = "server/index", apiPre
233
236
  break;
234
237
  }
235
238
  }
236
- if (hasCustomServer) return `import '${virtualSetupId}';
237
- export * from '${customServerPath}';
238
- export { default } from '${customServerPath}';`;
239
- return String.raw`import '${virtualSetupId}';
240
- import { renderPage } from 'vike-lite/server';
239
+ if (hasCustomServer) return `import '${virtualSetupId}';` + (prerender ? `export{routes}from'${virtualModuleId}';` : "") + `export * from'${customServerPath}';export{default}from'${customServerPath}';`;
240
+ return `import '${virtualSetupId}';` + (prerender ? `export{routes}from'${virtualModuleId}';` : "") + `import { renderPage } from 'vike-lite/server';
241
241
  export default {
242
242
  async fetch(request) {
243
243
  return renderPage(request);
@@ -326,11 +326,67 @@ if (process.env.NODE_ENV === 'production') {
326
326
  const { PORT } = process.env;
327
327
  const port = PORT ? Number.parseInt(PORT) : 3000;
328
328
  server.listen(port, () => {
329
- console.log('\n\x1b[32m🚀 Server is running at http://localhost:' + port + '\x1b[0m\n');
329
+ console.log('\n\u{1B}[32m🚀 Server is running at http://localhost:' + port + '\u{1B}[0m\n');
330
330
  });
331
331
  }`;
332
332
  }
333
333
  },
334
+ async closeBundle() {
335
+ if (!prerender || !isProd || !import.meta.env.SSR) return;
336
+ await new Promise((resolve) => setTimeout(resolve, 500));
337
+ const { pathToFileURL } = await import("node:url");
338
+ const serverEntryPath = path.resolve(viteConfigRoot, outDir, "server/index.mjs");
339
+ if (!fs.existsSync(serverEntryPath)) return;
340
+ const serverModule = await import(pathToFileURL(serverEntryPath).href);
341
+ const app = serverModule.default;
342
+ const routes = serverModule.routes || [];
343
+ const urlsToPrerender = /* @__PURE__ */ new Set();
344
+ for (const route of routes) {
345
+ let shouldPrerender = true;
346
+ let dynamicUrls = [];
347
+ if (route.Prerender) {
348
+ const mod = await route.Prerender();
349
+ const prerenderFn = mod.default ?? mod.prerender;
350
+ const result = typeof prerenderFn === "function" ? await prerenderFn() : prerenderFn;
351
+ if (result === false) shouldPrerender = false;
352
+ else if (result === true) shouldPrerender = true;
353
+ else if (Array.isArray(result)) {
354
+ shouldPrerender = true;
355
+ dynamicUrls = result;
356
+ }
357
+ }
358
+ if (shouldPrerender) {
359
+ if (!route.path.includes(":")) urlsToPrerender.add(route.path === "/" ? "/" : route.path);
360
+ for (const url of dynamicUrls) urlsToPrerender.add(url);
361
+ }
362
+ }
363
+ if (urlsToPrerender.size === 0) return;
364
+ console.log("\n\x1B[36m📦 Starting Static Site Generation (SSG)...\x1B[0m");
365
+ const base = process.env.BASE_URL || "/";
366
+ const baseNoSlash = base.endsWith("/") ? base.slice(0, -1) : base;
367
+ let generatedCount = 0;
368
+ const clientDir = path.resolve(viteConfigRoot, outDir, "client");
369
+ for (const urlPath of urlsToPrerender) {
370
+ const htmlReq = new Request(`http://localhost${baseNoSlash}${urlPath}`);
371
+ const htmlRes = await app.fetch(htmlReq);
372
+ if (htmlRes.ok && htmlRes.headers.get("content-type")?.includes("text/html")) {
373
+ const outDirRoute = path.join(clientDir, urlPath === "/" ? "" : urlPath);
374
+ fs.mkdirSync(outDirRoute, { recursive: true });
375
+ fs.writeFileSync(path.join(outDirRoute, "index.html"), await htmlRes.text());
376
+ } else console.error(`\u{1B}[31m✖ SSG HTML Error for ${urlPath}\u{1B}[0m`);
377
+ const jsonTarget = urlPath === "/" ? "/index" : urlPath;
378
+ const jsonReq = new Request(`http://localhost${baseNoSlash}${jsonTarget}.pageContext.json`);
379
+ const jsonRes = await app.fetch(jsonReq);
380
+ if (jsonRes.ok) {
381
+ const jsonOutPath = path.join(clientDir, `${jsonTarget}.pageContext.json`);
382
+ fs.mkdirSync(path.dirname(jsonOutPath), { recursive: true });
383
+ fs.writeFileSync(jsonOutPath, await jsonRes.text());
384
+ } else console.error(`\u{1B}[31m✖ SSG JSON Error for ${jsonTarget}\u{1B}[0m`);
385
+ console.log(`\u{1B}[32m✓\u{1B}[0m Pre-rendered: ${urlPath}`);
386
+ generatedCount++;
387
+ }
388
+ console.log(`\n\u{1B}[32m✨ SSG Completed! Generated ${generatedCount} static routes.\u{1B}[0m\n`);
389
+ },
334
390
  configureServer(server) {
335
391
  return () => {
336
392
  const pagesPath = path.resolve(viteConfigRoot, pagesDir);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vike-lite",
3
- "version": "1.6.1",
3
+ "version": "1.7.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "module": "./dist/index.mjs",
@@ -41,9 +41,9 @@
41
41
  "build": "tsdown"
42
42
  },
43
43
  "devDependencies": {
44
- "@types/node": "^26.0.1",
44
+ "@types/node": "^26.1.0",
45
45
  "tsdown": "^0.22.3",
46
- "vite": "^8.1.0"
46
+ "vite": "^8.1.3"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "vite": ">=8"