前端打包优化分析

起因:公司基于 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 资源总量,为提升页面加载速度创造了有利条件。

相关推荐
OEC小胖胖3 分钟前
【React Hooks】封装的艺术:如何编写高质量的 React 自-定义 Hooks
前端·react.js·前端框架·web
BillKu11 分钟前
vue3+element-plus 输入框el-input设置背景颜色和字体颜色,样式效果等同于不可编辑的效果
前端·javascript·vue.js
惊悚的毛毛虫16 分钟前
掘金免广告?不想看理财交流圈?不想看exp+8?
前端
springfe010121 分钟前
vue3组件 - 大文件上传
前端·vue.js
再学一点就睡30 分钟前
Vite 工作原理(简易版)—— 从代码看核心逻辑
前端·vite
好好好明天会更好1 小时前
uniapp项目中小程序的生命周期
前端·vue.js
CF14年老兵1 小时前
「Vue 3 + View Transition 实现炫酷圆形缩放换肤动画」
前端·css·trae
小璞1 小时前
05_CursorRules_代码审查篇_Rule_code-review
前端
前端小书童1 小时前
前端开发中的css:「ink → Bootstrap → 预处理器 → Tailwind → UnoCSS」
前端·css