Skip to content

Commit 4cb2abb

Browse files
authored
fix: use a recursive helper to find named parent package (#507)
* fix: use a recursive helper to find named parent package, catch errors to avoid breaking the process just because stats didn't work * fix: ensure parsed package cache is hit by normalizing cached paths, skip over same package * refactor: use new predicate arg of vitefu to avoid recursion * fix: normalize stat filenames to ensure cached package names are actually hit on aggregation.
1 parent dd5a8c2 commit 4cb2abb

File tree

4 files changed

+60
-44
lines changed

4 files changed

+60
-44
lines changed

.changeset/dry-seahorses-sin.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/vite-plugin-svelte': patch
3+
---
4+
5+
improve robustness of compile stats taking

packages/vite-plugin-svelte/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
"kleur": "^4.1.5",
5353
"magic-string": "^0.26.7",
5454
"svelte-hmr": "^0.15.1",
55-
"vitefu": "^0.2.1"
55+
"vitefu": "^0.2.2"
5656
},
5757
"peerDependencies": {
5858
"diff-match-patch": "^1.0.5",

packages/vite-plugin-svelte/src/utils/vite-plugin-svelte-stats.ts

Lines changed: 50 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ import { log } from './log';
22
//eslint-disable-next-line node/no-missing-import
33
import { findClosestPkgJsonPath } from 'vitefu';
44
import { readFileSync } from 'fs';
5+
import { dirname } from 'path';
56
import { performance } from 'perf_hooks';
7+
import { normalizePath } from 'vite';
68

79
interface Stat {
810
file: string;
@@ -85,6 +87,27 @@ function formatPackageStats(pkgStats: PackageStats[]) {
8587
return table;
8688
}
8789

90+
/**
91+
* utility to get the package name a file belongs to
92+
*
93+
* @param {string} file to find package for
94+
* @returns {path:string,name:string} tuple of path,name where name is the parsed package name and path is the normalized path to it
95+
*/
96+
async function getClosestNamedPackage(file: string): Promise<{ name: string; path: string }> {
97+
let name = '$unknown';
98+
let path = await findClosestPkgJsonPath(file, (pkgPath) => {
99+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
100+
if (pkg.name != null) {
101+
name = pkg.name;
102+
return true;
103+
}
104+
return false;
105+
});
106+
// return normalized path with appended '/' so .startsWith works for future file checks
107+
path = normalizePath(dirname(path ?? file)) + '/';
108+
return { name, path };
109+
}
110+
88111
export class VitePluginSvelteStats {
89112
// package directory -> package name
90113
private _packages: { path: string; name: string }[] = [];
@@ -108,6 +131,7 @@ export class VitePluginSvelteStats {
108131
if (collection.finished) {
109132
throw new Error('called after finish() has been used');
110133
}
134+
file = normalizePath(file);
111135
const start = performance.now();
112136
const stat: Stat = { file, start, end: start };
113137
return () => {
@@ -133,54 +157,41 @@ export class VitePluginSvelteStats {
133157
}
134158

135159
private async _finish(collection: StatCollection) {
136-
collection.finished = true;
137-
const now = performance.now();
138-
collection.duration = now - collection.collectionStart;
139-
const logResult = collection.options.logResult(collection);
140-
if (logResult) {
141-
await this._aggregateStatsResult(collection);
142-
log.info(`${collection.name} done.`, formatPackageStats(collection.packageStats!));
143-
}
144-
// cut some ties to free it for garbage collection
145-
const index = this._collections.indexOf(collection);
146-
this._collections.splice(index, 1);
147-
collection.stats.length = 0;
148-
collection.stats = [];
149-
if (collection.packageStats) {
150-
collection.packageStats.length = 0;
151-
collection.packageStats = [];
160+
try {
161+
collection.finished = true;
162+
const now = performance.now();
163+
collection.duration = now - collection.collectionStart;
164+
const logResult = collection.options.logResult(collection);
165+
if (logResult) {
166+
await this._aggregateStatsResult(collection);
167+
log.info(`${collection.name} done.`, formatPackageStats(collection.packageStats!));
168+
}
169+
// cut some ties to free it for garbage collection
170+
const index = this._collections.indexOf(collection);
171+
this._collections.splice(index, 1);
172+
collection.stats.length = 0;
173+
collection.stats = [];
174+
if (collection.packageStats) {
175+
collection.packageStats.length = 0;
176+
collection.packageStats = [];
177+
}
178+
collection.start = () => () => {};
179+
collection.finish = () => {};
180+
} catch (e) {
181+
// this should not happen, but stats taking also should not break the process
182+
log.debug.once(`failed to finish stats for ${collection.name}`, e);
152183
}
153-
collection.start = () => () => {};
154-
collection.finish = () => {};
155184
}
156185

157186
private async _aggregateStatsResult(collection: StatCollection) {
158187
const stats = collection.stats;
159188
for (const stat of stats) {
160189
let pkg = this._packages.find((p) => stat.file.startsWith(p.path));
161190
if (!pkg) {
162-
// check for package.json first
163-
let pkgPath = await findClosestPkgJsonPath(stat.file);
164-
if (pkgPath) {
165-
let path = pkgPath?.replace(/package.json$/, '');
166-
let name = JSON.parse(readFileSync(pkgPath, 'utf-8')).name;
167-
if (!name) {
168-
// some packages have nameless nested package.json
169-
pkgPath = await findClosestPkgJsonPath(path);
170-
if (pkgPath) {
171-
path = pkgPath?.replace(/package.json$/, '');
172-
name = JSON.parse(readFileSync(pkgPath, 'utf-8')).name;
173-
}
174-
}
175-
if (path && name) {
176-
pkg = { path, name };
177-
this._packages.push(pkg);
178-
}
179-
}
191+
pkg = await getClosestNamedPackage(stat.file);
192+
this._packages.push(pkg);
180193
}
181-
// TODO is it possible that we want to track files where there is no named packge.json as parent?
182-
// what do we want to do for that, try to find common root paths for different stats?
183-
stat.pkg = pkg?.name ?? '$unknown';
194+
stat.pkg = pkg.name;
184195
}
185196

186197
// group stats

pnpm-lock.yaml

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)