vike-lite 1.16.2 → 1.17.1

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
@@ -29,13 +29,30 @@ export default {
29
29
  vikeLite({
30
30
  pagesDir: 'pages', // Default: Directory containing your pages
31
31
  apiPrefix: '/api', // Default: Prefix to bypass SSR for API routes
32
- prerender: false // Default: Enable SSG globally
32
+ prerender: false, // Default: Enable SSG globally
33
33
  serverEntry: 'server/index', // Default: unfedined value that allows to use a custom server entry file
34
+ printDependencies: false // Default: Print, per build (client/server), which package.json dependencies ended up in the bundle
34
35
  })
35
36
  ]
36
37
  } satisfies UserConfig
37
38
  ```
38
39
 
40
+ #### printDependencies
41
+
42
+ When set to `true`, at the end of each production build (client and server) the plugin prints the list of `package.json` dependencies (and devDependencies) that were actually bundled or externally imported in that specific build output. This is useful to debug bundle composition/size — e.g. spotting a heavy dependency that unexpectedly ended up in the client bundle.
43
+
44
+ ```sh
45
+
46
+ 📦 [Client bundle] package.json dependencies used (1):
47
+ - solid-js@^1.9.3
48
+
49
+ 📦 [Server bundle] package.json dependencies used (2):
50
+ - solid-js@^1.9.3
51
+ - hono@^4.12.31
52
+ ```
53
+
54
+ It's disabled by default since it only adds diagnostic console output and isn't needed for normal usage.
55
+
39
56
  ### 🖥️ Server Integration
40
57
 
41
58
  #### `renderPage()`
@@ -1,4 +1,4 @@
1
- import { t as VikeState } from "../store-9UNcAe5D.mjs";
1
+ import { t as VikeState } from "../store-DRuFjsY3.mjs";
2
2
  //#region src/__internal/client.d.ts
3
3
  declare function createLinkClickHandler(onNavigate: (url: URL) => void): (e: MouseEvent) => void;
4
4
  declare function createLinkPrefetchHandler(onPrefetch: (url: URL) => void): (e: Event) => void;
@@ -1,4 +1,4 @@
1
- import { n as setVikeState, r as store, t as VikeState } from "../store-9UNcAe5D.mjs";
1
+ import { n as setVikeState, r as store, t as VikeState } from "../store-DRuFjsY3.mjs";
2
2
  //#region src/__internal/server.d.ts
3
3
  interface HtmlShellParams {
4
4
  pageTitleTag: string;
@@ -1,4 +1,4 @@
1
- import { n as store, t as setVikeState } from "../store-BCs8gL_o.mjs";
1
+ import { n as store, t as setVikeState } from "../store-D-6PbvfY.mjs";
2
2
  //#region src/__internal/server.ts
3
3
  /**
4
4
  * Renders the HTML document shell shared by every adapter: doctype, meta tags,
@@ -1,8 +1,6 @@
1
+ import { t as escapeRegex } from "../shared-Dh8Fb_3P.mjs";
1
2
  //#region src/__internal/shared.ts
2
3
  const regexCache = /* @__PURE__ */ new Map();
3
- function escapeRegex(str) {
4
- return str.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`);
5
- }
6
4
  function matchRoute(urlPathname, routes) {
7
5
  for (const route of routes) {
8
6
  if (!route.path.includes(":")) {
package/dist/server.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { BASE_URL, matchRoute, stripBase } from "./__internal/shared.mjs";
2
2
  import { AbortRedirect, AbortRender } from "./server/abort.mjs";
3
- import { n as store } from "./store-BCs8gL_o.mjs";
3
+ import { n as store } from "./store-D-6PbvfY.mjs";
4
4
  //#region src/utils/serializeContext.ts
5
5
  const ESCAPE_LOOKUP = {
6
6
  "&": String.raw`\u0026`,
@@ -0,0 +1,6 @@
1
+ //#region src/shared/index.ts
2
+ function escapeRegex(str) {
3
+ return str.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`);
4
+ }
5
+ //#endregion
6
+ export { escapeRegex as t };
@@ -1,4 +1,4 @@
1
- //#region src/server/store.ts
1
+ //#region src/shared/store.ts
2
2
  const KEY = Symbol.for("vike-lite:store");
3
3
  const store = globalThis[KEY] ??= {
4
4
  routes: [],
@@ -1,4 +1,4 @@
1
- //#region src/server/store.d.ts
1
+ //#region src/shared/store.d.ts
2
2
  interface VikeState {
3
3
  routes: typeof import('virtual:vike-lite/routes')['routes'] | [];
4
4
  errorRoute: typeof import('virtual:vike-lite/routes')['errorRoute'] | null;
package/dist/vite.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Plugin } from "vite";
2
2
  //#region src/vite/index.d.ts
3
- declare function vikeLite({ pagesDir, apiPrefix, prerender, serverEntry }?: {
3
+ declare function vikeLite({ pagesDir, apiPrefix, prerender, serverEntry, printDependencies }?: {
4
4
  /**
5
5
  * The directory where your page components are located.
6
6
  * This is where the plugin will look for your page files to generate routes.
@@ -26,6 +26,14 @@ declare function vikeLite({ pagesDir, apiPrefix, prerender, serverEntry }?: {
26
26
  * @default undefined
27
27
  */
28
28
  serverEntry?: string | false;
29
+ /**
30
+ * Whether to print, at the end of each build (client and server), the list of
31
+ * package.json dependencies that ended up in that bundle. Useful to debug bundle
32
+ * size/composition, but adds console output on every production build, so it's
33
+ * disabled by default.
34
+ * @default false
35
+ */
36
+ printDependencies?: boolean;
29
37
  }): Plugin;
30
38
  //#endregion
31
39
  export { vikeLite as default };
package/dist/vite.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ import { t as escapeRegex } from "./shared-Dh8Fb_3P.mjs";
1
2
  import fs from "node:fs";
2
3
  import path from "node:path";
3
4
  import { Readable } from "node:stream";
@@ -109,13 +110,36 @@ const SUPPORTED_RENDERERS = [
109
110
  "vue"
110
111
  ];
111
112
  //#endregion
113
+ //#region src/vite/printDependencies.ts
114
+ function findPackageJsonPath(startDir) {
115
+ let dir = startDir;
116
+ while (true) {
117
+ const candidate = path.join(dir, "package.json");
118
+ if (fs.existsSync(candidate)) return candidate;
119
+ const parent = path.dirname(dir);
120
+ if (parent === dir) return null;
121
+ dir = parent;
122
+ }
123
+ }
124
+ function extractPackageNameFromPath(moduleId) {
125
+ const matches = [...moduleId.replaceAll("\\", "/").matchAll(/node_modules\/(@[^/]+\/[^/]+|[^/]+)/g)];
126
+ if (matches.length === 0) return null;
127
+ return matches[matches.length - 1][1];
128
+ }
129
+ function extractPackageNameFromImport(imp) {
130
+ if (imp.startsWith(".") || imp.startsWith("/") || imp.startsWith("\0") || path.isAbsolute(imp) || imp.startsWith("node:")) return null;
131
+ const parts = imp.split("/");
132
+ return imp.startsWith("@") && parts.length > 1 ? `${parts[0]}/${parts[1]}` : parts[0];
133
+ }
134
+ //#endregion
112
135
  //#region src/vite/index.ts
113
- function vikeLite({ pagesDir = "pages", apiPrefix = "/api", prerender = false, serverEntry } = {}) {
136
+ function vikeLite({ pagesDir = "pages", apiPrefix = "/api", prerender = false, serverEntry, printDependencies = false } = {}) {
114
137
  const isProd = process.env.NODE_ENV === "production";
115
138
  let viteConfigRoot;
116
139
  let outDir;
117
140
  let hasAnyPrerender;
118
141
  let baseUrl;
142
+ let projectDependencies = null;
119
143
  const VIRTUAL = {
120
144
  routes: "virtual:vike-lite/routes",
121
145
  manifest: "virtual:vike-lite/client-manifest",
@@ -139,10 +163,24 @@ function vikeLite({ pagesDir = "pages", apiPrefix = "/api", prerender = false, s
139
163
  outDir = config.build?.outDir ?? "dist";
140
164
  const { emptyOutDir, minify = true, cssMinify = true, sourcemap } = config.build || {};
141
165
  viteConfigRoot = config.root ? path.resolve(config.root) : process.cwd();
166
+ if (isProd && printDependencies) {
167
+ const pkgJsonPath = findPackageJsonPath(viteConfigRoot);
168
+ if (pkgJsonPath) {
169
+ const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, "utf8"));
170
+ projectDependencies = {
171
+ ...pkgJson.dependencies,
172
+ ...pkgJson.devDependencies,
173
+ ...pkgJson.peerDependencies
174
+ };
175
+ }
176
+ }
142
177
  const { routes } = generateRoutes(viteConfigRoot, pagesDir);
143
178
  hasAnyPrerender = prerender || routes.some((r) => r.prerender);
144
179
  const serverInput = { index: VIRTUAL.entryServer };
145
180
  if (hasAnyPrerender) serverInput.prerender = VIRTUAL.entryPrerender;
181
+ const escapedPagesDir = escapeRegex(pagesDir);
182
+ const pagesDirRegex = new RegExp(String.raw`[\\/]${escapedPagesDir}[\\/]([^\\/]+)[\\/]`);
183
+ const pagesDirTest = new RegExp(String.raw`[\\/]${escapedPagesDir}[\\/]`);
146
184
  return {
147
185
  appType: "custom",
148
186
  ssr: { noExternal: [/^vike-lite(?:$|-)/] },
@@ -182,15 +220,15 @@ function vikeLite({ pagesDir = "pages", apiPrefix = "/api", prerender = false, s
182
220
  },
183
221
  {
184
222
  name(moduleId) {
185
- const match = moduleId.match(new RegExp(String.raw`[\\/]${pagesDir}[\\/]([^\\/]+)[\\/]`));
223
+ const match = moduleId.match(pagesDirRegex);
186
224
  return match ? `page-${match[1]}` : "shared";
187
225
  },
188
- test: new RegExp(String.raw`[\\/]${pagesDir}[\\/]`),
226
+ test: pagesDirTest,
189
227
  priority: 10
190
228
  },
191
229
  {
192
230
  name(moduleId) {
193
- const match = moduleId.match(new RegExp(String.raw`[\\/]${pagesDir}[\\/]([^\\/]+)[\\/]`));
231
+ const match = moduleId.match(pagesDirRegex);
194
232
  return match ? `css-${match[1]}` : "css-shared";
195
233
  },
196
234
  test: /\.css$/,
@@ -294,6 +332,32 @@ function vikeLite({ pagesDir = "pages", apiPrefix = "/api", prerender = false, s
294
332
  }
295
333
  if (id === RESOLVED.entryPrerender) return importSetup + `export{routes}from'${VIRTUAL.routes}';export{renderPage}from'vike-lite/server';`;
296
334
  },
335
+ generateBundle(_options, bundle) {
336
+ if (!printDependencies || !projectDependencies) return;
337
+ const envName = this.environment.name;
338
+ if (envName !== "client" && envName !== "ssr") return;
339
+ const usedPackages = /* @__PURE__ */ new Set();
340
+ for (const file of Object.values(bundle)) {
341
+ if (file.type !== "chunk") continue;
342
+ for (const moduleId of file.moduleIds) {
343
+ const pkgName = extractPackageNameFromPath(moduleId);
344
+ if (pkgName && projectDependencies[pkgName] !== void 0) usedPackages.add(pkgName);
345
+ }
346
+ for (const imp of file.imports) {
347
+ const pkgName = extractPackageNameFromImport(imp);
348
+ if (pkgName && projectDependencies[pkgName] !== void 0) usedPackages.add(pkgName);
349
+ }
350
+ for (const imp of file.dynamicImports) {
351
+ const pkgName = extractPackageNameFromImport(imp);
352
+ if (pkgName && projectDependencies[pkgName] !== void 0) usedPackages.add(pkgName);
353
+ }
354
+ }
355
+ const label = envName === "client" ? "Client" : "Server";
356
+ const sorted = [...usedPackages].sort();
357
+ console.log(`📦 [${label} bundle] package.json dependencies used (${sorted.length}):`);
358
+ if (sorted.length === 0) console.log(` (None)`);
359
+ else for (const dep of sorted) console.log(` - ${dep}@${projectDependencies[dep]}`);
360
+ },
297
361
  closeBundle: {
298
362
  order: "pre",
299
363
  async handler() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vike-lite",
3
- "version": "1.16.2",
3
+ "version": "1.17.1",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",