前端打包优化分析

起因:公司基于 Vue2 框架开发的旧项目,经过长期迭代后,项目依赖包日益繁杂,打包体积也不断膨胀。其中,chunk-vendors.**.js 文件即便经过压缩处理,大小仍达到了惊人的 4.33M,这一情况已严重拖慢了首屏加载速度。这里专门记录一下打包优化的具体步骤,以便后续参考复用。

1. 静态资源优化

在前端项目里,静态图片资源是影响首屏加载速度的重要因素。旧项目经过长期迭代,积累了不少静态图片,若处理不当,会显著拖慢加载速度。所以,对静态图片资源进行优化是打包优化中很关键的一步。

image-webpack-loader 是一个用于 Webpack 的图像加载器模块,主要用于压缩和优化 PNG、JPEG、GIF、SVG 和 WEBP 格式的图像文件。该项目的主要编程语言是 JavaScript,适用于前端开发中的图像优化需求。

webpack配置

js 复制代码
module.exports = {
  chainWebpack: config => {
      config.module.rule('images')
          .test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)
          .use('image-webpack-loader')
            .loader('image-webpack-loader')
            .options({
              mozjpeg: { progressive: true, quality: 65 },
              optipng: { enabled: false },
              pngquant: { quality: [0.65, 0.90], speed: 4 },
              gifsicle: { interlaced: false }
            })
          .end()
  }
}

优化前体积:

优化后体积:

项目静态图片文件减少了72%

2. 大文件定位

需要明确哪些模块占用了大量空间,定位问题源头

这里使用了 Webpack Bundle Analyzer可视化工具,用于分析 Webpack 生成的 bundle 文件,帮助开发者优化前端项目的打包体积。

js 复制代码
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
   configureWebpack: {
     plugins: [
         new BundleAnalyzerPlugin()
     ]
  }
}

完成配置后,进行构建命令yarn build Webpack Bundle Analyzer 会自动启动一个本地服务器,并在浏览器中打开可视化界面。默认地址为 http://127.0.0.1:8888

这里可以看到chunk-vendors.**.js文件几乎占了半壁江山,其次是ts.worker.js

先来说说ts.worker.js。这个是TypeScript 编译器的 Web Worker 脚本文件,且是异步加载方式引入的,优化点不多。

然后是app.**.js,项目中存在不少体积较大的 SVG 文件与 views 文件。其中,views 文件作为各页面的代码载体,需结合具体业务场景逐步调整优化;而 SVG 文件则具备更直接的优化空间,可优先进行针对性处理。

SVG 文件的优化要点主要有两方面:

  1. 核查使用状态:长期迭代的项目中,静态资源的更替与删减难免导致部分 SVG 文件闲置。对此,我将通过脚本对项目中所有 SVG 文件进行全面筛查,确认其是否被实际使用。
  2. 文件体积压缩,即针对体积较大的 SVG 文件,通过压缩处理减小其占用空间。

经过脚本全面筛查,初步检测出 386 个未被引用的 SVG 文件;后续通过人工代码审查,最终确认其中 187 个为未使用文件。对这些文件进行处理后,app.**.js 文件的体积优化效果显著。后续可根据实际需求,针对体积较大的 SVG 文件的进一步压缩处理。

3.optimization.splitChunks

optimization 配置项是用于优化打包过程和输出结果的核心配置,对于首屏加载优化显著。

经过Webpack Bundle Analyzer对大文件进行的定位分析,chunk-vendors.**.js文件中包含多个体积较大的依赖包,针对这一情况,下一步将通过Optimization.splitChunks配置进行分包处理。

js 复制代码
module.exports = {
    optimization: {
      splitChunks: {
        chunks: 'all',
        cacheGroups: {
          vendor: {
            test: /[\/]node_modules[\/]/,
            name: 'vendors',
            chunks: 'all',
            priority: 10,
            enforce: true
          },
          antd: {
            test: /[\/]node_modules[\/]ant-design-vue[\/]/,
            name: 'antd',
            chunks: 'all',
            priority: 20
          },
          element: {
            test: /[\/]node_modules[\/]element-ui[\/]/,
            name: 'element',
            chunks: 'all',
            priority: 20
          },
          monaco: {
            test: /[\/]node_modules[\/]monaco-editor[\/]/,
            name: 'monaco',
            chunks: 'all',
            priority: 30
          },
          maxChart: {
            test: /[\/]node_modules[\/]max-charts[\/]/,
            name: 'maxChart',
            chunks: 'all',
            priority: 20
          },
          antV: {
            test: /[\/]node_modules[\/]@antv[\/]/,
            name: 'antV',
            chunks: 'all',
            priority: 20
          }
        }
      }
    }
}

综合以上分析,我筛选出五个体积较大的依赖包,并对其进行了分包处理。

需要注意的是splitChunks分包只是"优化打包规则",但无法改变 "代码的引入方式和执行逻辑",如入口内同步写入的文件仍会被打包到chunk文件中。

4.其他优化手段

  1. 路由懒加载

为所有路由添加 webpackChunkName 注释,使打包更有组织性,确保每个路由组件独立打包,避免嵌套引入导致体积集中。

js 复制代码
 {
      path: '/home',
      name: 'Home',
      // 单独打包为 home.[hash].js
      component: () => import(/* webpackChunkName: "home" */ '@/views/Home.vue')
    },
  1. 第三方库通过 CDN 引入

直接在public/index.html中通过 CDN 引入,免除打包环节

  1. 启用 Gzip/Brotli 压缩

需要结合服务器配置(例如Nginx配置)

上述优化方案的实施效果同样显著,需要说明的是,其中第二项方案对内网场景下并不适用,其余两项方案已在本项目中采纳实施。

最后是成果展现

  • 主包chunk-vendors.**.js从 4.33M 缩减至 3.41M,缩减了 0.92M,缩减比例约为 21.2%
  • app.**.js从 1.22M(约 1249kb)缩减至 678kb,缩减了 571kb,缩减比例约为 45.7%。

总体缩减比例约为 26.7%,这一优化显著降低了首屏加载时的 JS 资源总量,为提升页面加载速度创造了有利条件。

相关推荐
非凡ghost4 分钟前
Affinity Photo(图像编辑软件) 多语便携版
前端·javascript·后端
非凡ghost6 分钟前
VideoProc Converter AI(视频转换软件) 多语便携版
前端·javascript·后端
endlesskiller12 分钟前
3年前我不会实现的,现在靠ai辅助实现了
前端·javascript
用户9047066835714 分钟前
commonjs的本质
前端
Sailing22 分钟前
5分钟搞定 DeepSeek API 配置:从配置到调用一步到位
前端·openai·ai编程
Pa2sw0rd丶25 分钟前
如何在 React 中实现键盘快捷键管理器以提升用户体验
前端·react.js
非凡ghost41 分钟前
ToDoList(开源待办事项列表) 中文绿色版
前端·javascript·后端
j七七1 小时前
5分钟搭微信自动回复机器人5分钟搭微信自动回复机器人
运维·服务器·开发语言·前端·python·微信
快起来别睡了1 小时前
TypeScript装饰器详解:像搭积木一样给代码加功能
前端·typescript
OpenTiny社区1 小时前
如何使用 TinyEditor 快速部署一个协同编辑器?
前端·vue.js