JavaScript 是网络上成本最高的资源——按字节计算,JavaScript 文件比同等大小的图片成本更高, 因为它必须被解析和执行,而不仅仅是解码。500 KB 的 JavaScript 包可以在中等性能手机上阻塞 主线程 2–4 秒。以下是将其降至 100 KB 以下的方法。
第一步:测量现状
优化之前,先审查当前的包。运行 npx @next/bundle-analyzer,通过 ANALYZE=true npm run build 启用。树状图显示哪些包最大,哪些页面包含哪些模块。
第二步:删除未使用的依赖项
| 包 | 大小 | 替代方案 | 替代大小 |
|---|---|---|---|
| moment.js | 67 KB | date-fns(tree-shaken) | 3–8 KB |
| lodash | 72 KB | lodash-es(tree-shaken) | 1–5 KB |
| axios | 14 KB | fetch(原生) | 0 KB |
| react-icons(全部) | 340 KB | 单独 SVG 导入 | 0.5 KB/图标 |
第三步:Tree-shaking
- 使用具名导入,而非从桶文件的默认导入。
- 避免在工具模块中使用副作用导入。
- 检查库的 package.json 是否有
sideEffects: false。
第四步:代码分割
Next.js 在页面级别自动分割代码。对于子页面分割,使用动态导入。好的候选项:富文本编辑器、 图表库、PDF 查看器、地图组件、标签页或弹窗后面初始不可见的组件。
第五步:优化第三方脚本
使用 Next.js 的 <Script> 组件处理第三方脚本:strategy="lazyOnload"(其他一切之后加载),strategy="afterInteractive"(水合后加载,适合大多数分析),strategy="worker"(在 Web Worker 中加载,完全离开主线程)。
前后对比:真实数据
| 指标 | 优化前 | 优化后 |
|---|---|---|
| 首页 JS(gzip) | 520 KB | 82 KB |
| 主线程阻塞时间 | 3.2 秒 | 0.4 秒 |
| INP(75 百分位) | 480 ms | 95 ms |
| Lighthouse 性能 | 61 | 94 |