vike-lite 1.17.1 → 1.17.3

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.
Files changed (3) hide show
  1. package/README.md +2 -2
  2. package/dist/vite.mjs +84 -30
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -43,10 +43,10 @@ When set to `true`, at the end of each production build (client and server) the
43
43
 
44
44
  ```sh
45
45
 
46
- šŸ“¦ [Client bundle] package.json dependencies used (1):
46
+ šŸ“¦ [Client bundle] 1 dependencies used from package.json:
47
47
  - solid-js@^1.9.3
48
48
 
49
- šŸ“¦ [Server bundle] package.json dependencies used (2):
49
+ šŸ“¦ [Server bundle] 2 dependencies used from package.json:
50
50
  - solid-js@^1.9.3
51
51
  - hono@^4.12.31
52
52
  ```
package/dist/vite.mjs CHANGED
@@ -121,15 +121,18 @@ function findPackageJsonPath(startDir) {
121
121
  dir = parent;
122
122
  }
123
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];
124
+ function extractPkgName(id) {
125
+ const normalized = id.replaceAll("\\", "/");
126
+ const matches = [...normalized.matchAll(/(?:node_modules|\.yarn(?:\/__virtual__)?)\/(@[^/]+\/[^/]+|[^/]+)/g)];
127
+ if (matches.length > 0) {
128
+ const pkg = matches[matches.length - 1][1];
129
+ if (pkg !== ".pnpm") return pkg;
130
+ }
131
+ if (!normalized.startsWith(".") && !normalized.startsWith("/") && !normalized.includes(":")) {
132
+ const parts = normalized.split("/");
133
+ return normalized.startsWith("@") && parts.length > 1 ? `${parts[0]}/${parts[1]}` : parts[0];
134
+ }
135
+ return null;
133
136
  }
134
137
  //#endregion
135
138
  //#region src/vite/index.ts
@@ -140,6 +143,8 @@ function vikeLite({ pagesDir = "pages", apiPrefix = "/api", prerender = false, s
140
143
  let hasAnyPrerender;
141
144
  let baseUrl;
142
145
  let projectDependencies = null;
146
+ const depUsage = /* @__PURE__ */ new Map();
147
+ const processedEnvs = /* @__PURE__ */ new Set();
143
148
  const VIRTUAL = {
144
149
  routes: "virtual:vike-lite/routes",
145
150
  manifest: "virtual:vike-lite/client-manifest",
@@ -167,10 +172,18 @@ function vikeLite({ pagesDir = "pages", apiPrefix = "/api", prerender = false, s
167
172
  const pkgJsonPath = findPackageJsonPath(viteConfigRoot);
168
173
  if (pkgJsonPath) {
169
174
  const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, "utf8"));
170
- projectDependencies = {
171
- ...pkgJson.dependencies,
172
- ...pkgJson.devDependencies,
173
- ...pkgJson.peerDependencies
175
+ projectDependencies = {};
176
+ for (const [k, v] of Object.entries(pkgJson.dependencies || {})) projectDependencies[k] = {
177
+ version: v,
178
+ type: ""
179
+ };
180
+ for (const [k, v] of Object.entries(pkgJson.devDependencies || {})) projectDependencies[k] = {
181
+ version: v,
182
+ type: "dev"
183
+ };
184
+ for (const [k, v] of Object.entries(pkgJson.peerDependencies || {})) if (!projectDependencies[k]) projectDependencies[k] = {
185
+ version: v,
186
+ type: "peer"
174
187
  };
175
188
  }
176
189
  }
@@ -336,27 +349,68 @@ function vikeLite({ pagesDir = "pages", apiPrefix = "/api", prerender = false, s
336
349
  if (!printDependencies || !projectDependencies) return;
337
350
  const envName = this.environment.name;
338
351
  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);
352
+ const usedDeps = /* @__PURE__ */ new Map();
353
+ for (const chunk of Object.values(bundle)) {
354
+ if (chunk.type !== "chunk") continue;
355
+ for (const id of chunk.moduleIds) {
356
+ const pkg = extractPkgName(id);
357
+ if (pkg && !pkg.startsWith("vike-lite") && Object.hasOwn(projectDependencies, pkg)) {
358
+ const entry = usedDeps.get(pkg) ?? {
359
+ ...projectDependencies[pkg],
360
+ isBundled: false,
361
+ isExternal: false
362
+ };
363
+ entry.isBundled = true;
364
+ usedDeps.set(pkg, entry);
365
+ }
345
366
  }
346
- for (const imp of file.imports) {
347
- const pkgName = extractPackageNameFromImport(imp);
348
- if (pkgName && projectDependencies[pkgName] !== void 0) usedPackages.add(pkgName);
367
+ for (const imp of [...chunk.imports, ...chunk.dynamicImports]) {
368
+ if (bundle[imp]) continue;
369
+ const pkg = extractPkgName(imp);
370
+ if (pkg && !pkg.startsWith("vike-lite") && Object.hasOwn(projectDependencies, pkg)) {
371
+ const entry = usedDeps.get(pkg) ?? {
372
+ ...projectDependencies[pkg],
373
+ isBundled: false,
374
+ isExternal: false
375
+ };
376
+ entry.isExternal = true;
377
+ usedDeps.set(pkg, entry);
378
+ }
349
379
  }
350
- for (const imp of file.dynamicImports) {
351
- const pkgName = extractPackageNameFromImport(imp);
352
- if (pkgName && projectDependencies[pkgName] !== void 0) usedPackages.add(pkgName);
380
+ }
381
+ for (const [name, info] of usedDeps) {
382
+ const global = depUsage.get(name) ?? {
383
+ version: info.version,
384
+ type: info.type,
385
+ isBundled: false,
386
+ isExternal: false,
387
+ externalEnvs: /* @__PURE__ */ new Set()
388
+ };
389
+ global.isBundled ||= info.isBundled;
390
+ global.isExternal ||= info.isExternal;
391
+ if (info.isExternal) global.externalEnvs.add(envName);
392
+ depUsage.set(name, global);
393
+ }
394
+ processedEnvs.add(envName);
395
+ const sorted = [...usedDeps.entries()].sort(([a], [b]) => a.localeCompare(b));
396
+ console.log(`\nšŸ“¦ [${envName === "client" ? "Client" : "Server"} bundle] ${sorted.length} dependencies used from package.json:`);
397
+ if (sorted.length === 0) console.log(" (None)");
398
+ else for (const [name, info] of sorted) {
399
+ const typeTag = info.type ? ` \u{1B}[33m[${info.type}]\u{1B}[0m` : "";
400
+ const usageTag = info.isExternal ? " \x1B[90m(external)\x1B[0m" : " \x1B[90m(bundled)\x1B[0m";
401
+ console.log(` - \u{1B}[36m${name}@${info.version}\u{1B}[0m${typeTag}${usageTag}`);
402
+ }
403
+ if (processedEnvs.has("client") && processedEnvs.has("ssr")) {
404
+ const suggestions = [];
405
+ for (const [name, info] of [...depUsage.entries()].sort(([a], [b]) => a.localeCompare(b))) if (info.externalEnvs.has("ssr") && info.type === "dev") suggestions.push(`\u{1B}[31m🚨 ${name}\u{1B}[0m is externalized in the server bundle but listed as a \u{1B}[33mdevDependency\u{1B}[0m. Move it to \u{1B}[32mdependencies\u{1B}[0m or it will break in production.`);
406
+ else if (info.type === "" && info.isBundled && !info.isExternal) suggestions.push(`\u{1B}[34mšŸ’” ${name}\u{1B}[0m is always fully bundled (never externalized). Consider moving it to \u{1B}[33mdevDependencies\u{1B}[0m to reduce production node_modules size.`);
407
+ const unusedRegularDeps = Object.entries(projectDependencies).filter(([name, info]) => info.type === "" && !depUsage.has(name)).sort(([a], [b]) => a.localeCompare(b));
408
+ for (const [name, info] of unusedRegularDeps) suggestions.push(`\u{1B}[90mšŸ—‘ļø ${name}@${info.version}\u{1B}[0m is listed in "dependencies" but wasn't found in any bundle — if it's only needed at build/dev time, move it to devDependencies (or remove it if unused).`);
409
+ if (suggestions.length > 0) {
410
+ console.log("\n \x1B[1mSuggestions:\x1B[0m");
411
+ for (const s of suggestions) console.log(` ${s}`);
353
412
  }
354
413
  }
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
414
  },
361
415
  closeBundle: {
362
416
  order: "pre",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vike-lite",
3
- "version": "1.17.1",
3
+ "version": "1.17.3",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",