Skip to content

Commit 78d9e6f

Browse files
committed
add
1 parent 907edd4 commit 78d9e6f

File tree

130 files changed

+12821
-483
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

130 files changed

+12821
-483
lines changed

analyze-bundle.js

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
const { resolve } = require('path');
2+
const fs = require('fs');
3+
4+
console.log('Starting bundle analysis...');
5+
6+
// Find the most recent Next.js build manifest
7+
const buildManifestPath = resolve('.next', 'build-manifest.json');
8+
9+
console.log(`Checking for build manifest at: ${buildManifestPath}`);
10+
11+
if (!fs.existsSync(buildManifestPath)) {
12+
console.error('Build manifest not found. Run `npm run build` first.');
13+
process.exit(1);
14+
}
15+
16+
console.log('Found build manifest. Loading...');
17+
const buildManifest = require(buildManifestPath);
18+
19+
// Extract all JavaScript chunks
20+
const jsFiles = new Set();
21+
22+
// Process polyfillFiles, devFiles, etc.
23+
const manifestCategories = [
24+
'polyfillFiles',
25+
'devFiles',
26+
'ampDevFiles',
27+
'lowPriorityFiles',
28+
'rootMainFiles'
29+
];
30+
31+
manifestCategories.forEach(category => {
32+
if (buildManifest[category] && Array.isArray(buildManifest[category])) {
33+
buildManifest[category].forEach(file => {
34+
if (file.endsWith('.js')) {
35+
jsFiles.add(file);
36+
}
37+
});
38+
}
39+
});
40+
41+
// Process pages
42+
if (buildManifest.pages) {
43+
Object.values(buildManifest.pages).forEach(filesArray => {
44+
if (Array.isArray(filesArray)) {
45+
filesArray.forEach(file => {
46+
if (file.endsWith('.js')) {
47+
jsFiles.add(file);
48+
}
49+
});
50+
}
51+
});
52+
}
53+
54+
console.log(`Found ${jsFiles.size} JavaScript files in the build manifest.`);
55+
56+
// Create stats for files
57+
const fileStats = Array.from(jsFiles).map(file => {
58+
const fullPath = resolve('.next', file);
59+
console.log(`Checking file size for: ${fullPath}`);
60+
61+
let size = 0;
62+
try {
63+
const stat = fs.statSync(fullPath);
64+
size = stat.size;
65+
console.log(`File size: ${size} bytes`);
66+
} catch (e) {
67+
console.warn(`Couldn't find file: ${fullPath}`, e);
68+
}
69+
70+
// Extract chunk name from path
71+
const name = file.split('/').pop();
72+
73+
return {
74+
path: file,
75+
name: name,
76+
size: size,
77+
sizeKB: (size / 1024).toFixed(2)
78+
};
79+
});
80+
81+
// Sort by size, largest first
82+
fileStats.sort((a, b) => b.size - a.size);
83+
84+
// Group by directories
85+
const groupedStats = {};
86+
fileStats.forEach(stat => {
87+
const parts = stat.path.split('/');
88+
const dir = parts.length > 2 ? parts.slice(0, -1).join('/') : 'root';
89+
90+
if (!groupedStats[dir]) {
91+
groupedStats[dir] = [];
92+
}
93+
94+
groupedStats[dir].push(stat);
95+
});
96+
97+
// Calculate total size
98+
const totalSize = fileStats.reduce((sum, file) => sum + file.size, 0);
99+
const totalSizeKB = (totalSize / 1024).toFixed(2);
100+
const totalSizeMB = (totalSize / (1024 * 1024)).toFixed(2);
101+
102+
// Generate HTML report
103+
const htmlReport = `
104+
<!DOCTYPE html>
105+
<html lang="en">
106+
<head>
107+
<meta charset="UTF-8">
108+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
109+
<title>Next.js Bundle Analysis</title>
110+
<style>
111+
body {
112+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
113+
max-width: 1200px;
114+
margin: 0 auto;
115+
padding: 20px;
116+
color: #333;
117+
}
118+
h1, h2 {
119+
border-bottom: 1px solid #eee;
120+
padding-bottom: 10px;
121+
}
122+
table {
123+
width: 100%;
124+
border-collapse: collapse;
125+
margin-bottom: 30px;
126+
}
127+
th, td {
128+
text-align: left;
129+
padding: 12px;
130+
border-bottom: 1px solid #ddd;
131+
}
132+
th {
133+
background-color: #f2f2f2;
134+
}
135+
tr:hover {
136+
background-color: #f5f5f5;
137+
}
138+
.group-header {
139+
margin-top: 30px;
140+
font-weight: bold;
141+
background-color: #e6e6e6;
142+
padding: 10px;
143+
}
144+
.bar {
145+
height: 20px;
146+
background-color: #4CAF50;
147+
display: inline-block;
148+
}
149+
.summary {
150+
background-color: #f8f9fa;
151+
padding: 15px;
152+
border-radius: 5px;
153+
margin-bottom: 20px;
154+
border-left: 5px solid #4CAF50;
155+
}
156+
</style>
157+
</head>
158+
<body>
159+
<h1>Next.js Bundle Analysis</h1>
160+
161+
<div class="summary">
162+
<h2>Summary</h2>
163+
<p>Total JavaScript size: ${totalSizeKB} KB (${totalSizeMB} MB)</p>
164+
<p>Total chunks: ${fileStats.length}</p>
165+
</div>
166+
167+
<h2>All Chunks by Size</h2>
168+
<table>
169+
<thead>
170+
<tr>
171+
<th>File</th>
172+
<th>Size (KB)</th>
173+
<th>Percentage</th>
174+
</tr>
175+
</thead>
176+
<tbody>
177+
${fileStats.map(file => {
178+
const percentage = ((file.size / totalSize) * 100).toFixed(2);
179+
const barWidth = Math.max(1, percentage);
180+
return `
181+
<tr>
182+
<td>${file.path}</td>
183+
<td>${file.sizeKB} KB</td>
184+
<td>
185+
<div class="bar" style="width: ${barWidth}%"></div>
186+
${percentage}%
187+
</td>
188+
</tr>
189+
`;
190+
}).join('')}
191+
</tbody>
192+
</table>
193+
194+
<h2>Chunks by Directory</h2>
195+
${Object.entries(groupedStats).map(([dir, files]) => {
196+
const dirSize = files.reduce((sum, file) => sum + file.size, 0);
197+
const dirSizeKB = (dirSize / 1024).toFixed(2);
198+
const dirPercentage = ((dirSize / totalSize) * 100).toFixed(2);
199+
200+
return `
201+
<div class="group-header">${dir} (${dirSizeKB} KB, ${dirPercentage}% of total)</div>
202+
<table>
203+
<thead>
204+
<tr>
205+
<th>File</th>
206+
<th>Size (KB)</th>
207+
<th>Percentage</th>
208+
</tr>
209+
</thead>
210+
<tbody>
211+
${files.map(file => {
212+
const percentage = ((file.size / dirSize) * 100).toFixed(2);
213+
const barWidth = Math.max(1, percentage);
214+
return `
215+
<tr>
216+
<td>${file.name}</td>
217+
<td>${file.sizeKB} KB</td>
218+
<td>
219+
<div class="bar" style="width: ${barWidth}%"></div>
220+
${percentage}%
221+
</td>
222+
</tr>
223+
`;
224+
}).join('')}
225+
</tbody>
226+
</table>
227+
`;
228+
}).join('')}
229+
</body>
230+
</html>
231+
`;
232+
233+
// Write HTML report
234+
const reportPath = 'bundle-report.html';
235+
fs.writeFileSync(reportPath, htmlReport);
236+
237+
console.log(`Bundle analysis report generated: ${reportPath}`);
238+
console.log('Open this file in your browser to view the report.')

0 commit comments

Comments
 (0)