Skip to content

Commit fbe2139

Browse files
committed
feat: vite builder basic
1 parent 383b305 commit fbe2139

File tree

4 files changed

+81
-127
lines changed

4 files changed

+81
-127
lines changed

packages/plugin-bundle-stats/mocks/fixtures/node-minimal/package-lock.json

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

packages/plugin-bundle-stats/mocks/fixtures/node-minimal/package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@
1010
"build:vite": "node vite.script.cjs"
1111
},
1212
"devDependencies": {
13+
"@rsbuild/core": "^1.0.18",
1314
"esbuild": "^0.24.1",
14-
"webpack": "^5.95.0",
15-
"webpack-cli": "^5.1.4",
15+
"rollup-plugin-webpack-stats": "^2.1.0",
1616
"ts-loader": "^9.5.1",
17-
"@rsbuild/core": "^1.0.18",
1817
"typescript": "^5.7.3",
19-
"vite": "^5.4.0"
18+
"vite": "^5.4.0",
19+
"webpack": "^5.95.0",
20+
"webpack-cli": "^5.1.4"
2021
}
2122
}

packages/plugin-bundle-stats/mocks/fixtures/node-minimal/vite.config.ts

Lines changed: 8 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,6 @@
11
import path from 'path';
2+
import webpackStatsPlugin from 'rollup-plugin-webpack-stats';
23
import { defineConfig } from 'vite';
3-
import type { Plugin } from 'vite';
4-
5-
/**
6-
* Custom Vite plugin to generate bundle stats in a format compatible with other bundlers.
7-
*/
8-
function bundleStatsPlugin(): Plugin {
9-
return {
10-
name: 'bundle-stats',
11-
generateBundle(_options: any, bundle: any) {
12-
const stats = {
13-
assets: [] as any[],
14-
chunks: [] as any[],
15-
modules: [] as any[],
16-
entrypoints: {} as Record<string, any>,
17-
};
18-
19-
// Process bundle to create stats structure
20-
for (const [fileName, chunk] of Object.entries(bundle)) {
21-
if (
22-
chunk &&
23-
typeof chunk === 'object' &&
24-
'type' in chunk &&
25-
chunk.type === 'chunk'
26-
) {
27-
const chunkCode =
28-
'code' in chunk && typeof chunk.code === 'string' ? chunk.code : '';
29-
const chunkName =
30-
'name' in chunk && typeof chunk.name === 'string'
31-
? chunk.name
32-
: fileName;
33-
const isEntry = 'isEntry' in chunk ? Boolean(chunk.isEntry) : false;
34-
const modules =
35-
'modules' in chunk && typeof chunk.modules === 'object'
36-
? chunk.modules
37-
: {};
38-
39-
// Add asset info
40-
stats.assets.push({
41-
name: fileName,
42-
size: Buffer.byteLength(chunkCode, 'utf8'),
43-
emitted: true,
44-
type: 'chunk',
45-
});
46-
47-
// Add chunk info
48-
stats.chunks.push({
49-
id: chunkName,
50-
names: chunkName !== fileName ? [chunkName] : [],
51-
files: [fileName],
52-
size: Buffer.byteLength(chunkCode, 'utf8'),
53-
modules: Object.keys(modules || {}).map(moduleId => ({
54-
identifier: moduleId,
55-
name: moduleId,
56-
size: 0, // Vite doesn't provide individual module sizes
57-
chunks: [chunkName],
58-
})),
59-
entry: isEntry,
60-
initial: isEntry,
61-
});
62-
63-
// Add entrypoint info if it's an entry chunk
64-
if (isEntry && chunkName) {
65-
stats.entrypoints[chunkName] = {
66-
name: chunkName,
67-
chunks: [chunkName],
68-
assets: [
69-
{
70-
name: fileName,
71-
size: Buffer.byteLength(chunkCode, 'utf8'),
72-
},
73-
],
74-
};
75-
}
76-
}
77-
}
78-
79-
// Emit the stats.json file
80-
this.emitFile({
81-
type: 'asset',
82-
fileName: 'stats.json',
83-
source: JSON.stringify(stats, null, 2),
84-
});
85-
},
86-
};
87-
}
884

895
export default defineConfig({
906
build: {
@@ -95,15 +11,19 @@ export default defineConfig({
9511
bin: path.resolve(__dirname, 'src/bin.ts'),
9612
},
9713
output: {
14+
assetFileNames: 'assets/[name].[hash][extname]',
15+
chunkFileNames: 'assets/[name].[hash].js',
9816
entryFileNames: 'static/js/[name].js',
99-
chunkFileNames: 'static/js/async/[name].[hash].js',
100-
assetFileNames: 'static/[ext]/[name].[ext]',
10117
},
102-
plugins: [bundleStatsPlugin()],
10318
},
10419
sourcemap: true,
10520
minify: false,
10621
},
22+
plugins: [
23+
webpackStatsPlugin({
24+
fileName: 'stats.json',
25+
}),
26+
],
10727
resolve: {
10828
alias: {
10929
'@': path.resolve(__dirname, 'src'),

packages/plugin-bundle-stats/src/lib/runner/unify/unify.vite.ts

Lines changed: 20 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,9 @@ import type {
77
export type ViteAsset = {
88
name: string;
99
size: number;
10-
emitted: boolean;
11-
type: string;
1210
};
1311

1412
export type ViteModule = {
15-
identifier: string;
1613
name: string;
1714
size: number;
1815
chunks: string[];
@@ -22,23 +19,15 @@ export type ViteChunk = {
2219
id: string;
2320
names: string[];
2421
files: string[];
25-
size: number;
26-
modules: ViteModule[];
2722
entry: boolean;
2823
initial: boolean;
2924
};
3025

31-
export type ViteEntrypoint = {
32-
name: string;
33-
chunks: string[];
34-
assets: Array<{ name: string; size: number }>;
35-
};
36-
3726
export type ViteCoreStats = {
27+
builtAt: number;
3828
assets: ViteAsset[];
3929
chunks: ViteChunk[];
4030
modules: ViteModule[];
41-
entrypoints: Record<string, ViteEntrypoint>;
4231
};
4332

4433
/**
@@ -54,41 +43,37 @@ export function unifyBundlerStats(stats: ViteCoreStats): UnifiedStats {
5443

5544
const modulesMap = new Map<string, ViteModule>();
5645
for (const module of stats.modules || []) {
57-
modulesMap.set(module.identifier, module);
46+
modulesMap.set(module.name, module);
5847
}
5948

60-
for (const asset of stats.assets) {
49+
// Filter out non-JS assets (like source maps)
50+
const jsAssets = stats.assets.filter(asset => asset.name.endsWith('.js'));
51+
52+
for (const asset of jsAssets) {
6153
const unifiedOutput: UnifiedStatsOutput = {
6254
path: asset.name,
6355
bytes: asset.size,
6456
imports: [],
6557
inputs: {},
6658
};
6759

68-
for (const [entryName, entrypoint] of Object.entries(
69-
stats.entrypoints || {},
70-
)) {
71-
if (
72-
entrypoint.assets.some(entryAsset => entryAsset.name === asset.name)
73-
) {
74-
unifiedOutput.entryPoint = entryName;
75-
break;
60+
// Find the chunk that contains this asset
61+
const chunk = stats.chunks.find(c => c.files.includes(asset.name));
62+
if (chunk) {
63+
// Set entry point if it's an entry chunk
64+
if (chunk.entry && chunk.names.length > 0) {
65+
unifiedOutput.entryPoint = chunk.names[0];
7666
}
77-
}
7867

79-
// Find chunks that include this asset
80-
const relatedChunks = stats.chunks.filter(chunk =>
81-
chunk.files.includes(asset.name),
82-
);
68+
// Find modules that belong to this chunk
69+
const chunkModules =
70+
stats.modules?.filter(module => module.chunks.includes(chunk.id)) || [];
8371

84-
for (const chunk of relatedChunks) {
85-
for (const module of chunk.modules || []) {
86-
const moduleInfo = modulesMap.get(module.identifier);
87-
if (moduleInfo) {
88-
unifiedOutput.inputs![moduleInfo.name] = {
89-
bytes: moduleInfo.size || 0,
90-
};
91-
}
72+
// Add inputs
73+
for (const module of chunkModules) {
74+
unifiedOutput.inputs![module.name] = {
75+
bytes: module.size,
76+
};
9277
}
9378
}
9479

0 commit comments

Comments
 (0)