123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
- const webpack = require('webpack')
- const path = require('path')
- const fs = require('fs')
- // 获取webpack配置
- const webpackConfig = require('../webpack.config.js')
- // 添加分析插件
- const analyzeConfig = {
- ...webpackConfig,
- plugins: [
- ...webpackConfig.plugins,
- new BundleAnalyzerPlugin({
- analyzerMode: 'static',
- reportFilename: 'bundle-report.html',
- openAnalyzer: true,
- generateStatsFile: true,
- statsFilename: 'bundle-stats.json',
- statsOptions: null,
- logLevel: 'info'
- })
- ]
- }
- // 运行分析
- console.log('🔍 开始分析打包结果...')
- webpack(analyzeConfig, (err, stats) => {
- if (err) {
- console.error('❌ 分析失败:', err)
- return
- }
- if (stats.hasErrors()) {
- console.error('❌ 构建过程中出现错误:')
- stats.compilation.errors.forEach(error => {
- console.error(error)
- })
- return
- }
- console.log('✅ 分析完成!')
- console.log('📊 报告文件已生成:')
- console.log(' - bundle-report.html (可视化报告)')
- console.log(' - bundle-stats.json (详细统计)')
- // 生成简单的性能报告
- const statsData = stats.toJson()
- const report = generatePerformanceReport(statsData)
-
- fs.writeFileSync(
- path.join(__dirname, '../performance-report.md'),
- report,
- 'utf8'
- )
-
- console.log(' - performance-report.md (性能报告)')
- })
- function generatePerformanceReport(stats) {
- const assets = stats.assets || []
- const chunks = stats.chunks || []
- const modules = stats.modules || []
- // 按类型分组资源
- const assetsByType = {
- js: assets.filter(asset => asset.name.endsWith('.js')),
- css: assets.filter(asset => asset.name.endsWith('.css')),
- images: assets.filter(asset => /\.(png|jpg|jpeg|gif|svg|webp)$/.test(asset.name)),
- fonts: assets.filter(asset => /\.(woff|woff2|eot|ttf|otf)$/.test(asset.name)),
- other: assets.filter(asset =>
- !asset.name.endsWith('.js') &&
- !asset.name.endsWith('.css') &&
- !/\.(png|jpg|jpeg|gif|svg|webp|woff|woff2|eot|ttf|otf)$/.test(asset.name)
- )
- }
- // 计算总大小
- const totalSize = assets.reduce((sum, asset) => sum + asset.size, 0)
- const jsSize = assetsByType.js.reduce((sum, asset) => sum + asset.size, 0)
- const cssSize = assetsByType.css.reduce((sum, asset) => sum + asset.size, 0)
- // 生成报告
- const report = `# 性能分析报告
- ## 📊 构建统计
- - **总文件数**: ${assets.length}
- - **总大小**: ${formatBytes(totalSize)}
- - **JS文件**: ${assetsByType.js.length} 个,${formatBytes(jsSize)}
- - **CSS文件**: ${assetsByType.css.length} 个,${formatBytes(cssSize)}
- - **图片文件**: ${assetsByType.images.length} 个
- - **字体文件**: ${assetsByType.fonts.length} 个
- - **其他文件**: ${assetsByType.other.length} 个
- ## 🎯 主要JS文件
- ${assetsByType.js
- .sort((a, b) => b.size - a.size)
- .slice(0, 10)
- .map(asset => `- **${asset.name}**: ${formatBytes(asset.size)}`)
- .join('\n')}
- ## 🎨 CSS文件
- ${assetsByType.css
- .sort((a, b) => b.size - a.size)
- .map(asset => `- **${asset.name}**: ${formatBytes(asset.size)}`)
- .join('\n')}
- ## 📦 Chunk分析
- ${chunks
- .sort((a, b) => b.size - a.size)
- .slice(0, 10)
- .map(chunk => `- **${chunk.names.join(', ')}**: ${formatBytes(chunk.size)}`)
- .join('\n')}
- ## 🔍 大文件警告
- ${assets
- .filter(asset => asset.size > 1024 * 1024) // 1MB以上
- .sort((a, b) => b.size - a.size)
- .map(asset => `- ⚠️ **${asset.name}**: ${formatBytes(asset.size)} (建议优化)`)
- .join('\n') || '✅ 没有超过1MB的文件'}
- ## 📈 性能建议
- ### 🚀 已实施的优化
- - ✅ 代码分割 (${chunks.length} 个chunk)
- - ✅ 资源压缩
- - ✅ 缓存策略
- - ✅ 预加载关键资源
- ### 🎯 进一步优化建议
- ${generateOptimizationSuggestions(assets, chunks)}
- ---
- *报告生成时间: ${new Date().toLocaleString()}*
- `
- return report
- }
- function generateOptimizationSuggestions(assets, chunks) {
- const suggestions = []
-
- // 检查大文件
- const largeFiles = assets.filter(asset => asset.size > 500 * 1024) // 500KB以上
- if (largeFiles.length > 0) {
- suggestions.push('- 考虑进一步分割大文件或使用动态导入')
- }
-
- // 检查chunk数量
- if (chunks.length > 20) {
- suggestions.push('- Chunk数量较多,考虑合并相关功能')
- }
-
- // 检查图片优化
- const images = assets.filter(asset => /\.(png|jpg|jpeg|gif|svg)$/.test(asset.name))
- const largeImages = images.filter(asset => asset.size > 100 * 1024) // 100KB以上
- if (largeImages.length > 0) {
- suggestions.push('- 优化大图片,考虑使用WebP格式')
- }
-
- if (suggestions.length === 0) {
- suggestions.push('- 当前配置已经相当优化!')
- }
-
- return suggestions.join('\n')
- }
- function formatBytes(bytes) {
- if (bytes === 0) return '0 Bytes'
- const k = 1024
- const sizes = ['Bytes', 'KB', 'MB', 'GB']
- const i = Math.floor(Math.log(bytes) / Math.log(k))
- return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
- }
|