前端打包优化分析

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

相关推荐
AlienZHOU21 分钟前
AI Coding 时代下,我的技术面试实践分享
前端·后端·面试
Captaincc4 小时前
AI用量v0.1.11更新发布 新增 jusage doctor 诊断指令 托盘展示token 和余额 新增 AutoClaw 支持
前端·后端·vibecoding
计算机魔术师5 小时前
德国Wiki被黑后两周,OpenAI终于把模型失控的账本摊开了
前端
kyriewen5 小时前
我让 AI 当面试官面了我一轮:第 3 个追问我就卡住了(附 10 道追问清单)
前端·面试·ai编程
IT_陈寒6 小时前
Python的GIL把我坑惨了,多线程跑得比单线程还慢
前端·人工智能·后端
前端snow6 小时前
ai agent --- 多agent框架之图编排引擎-langgraph
前端
竹林8186 小时前
OmniPic Studio v3.2.1 核心技术架构与全平台发版解析文档
前端·浏览器
JamesZhang800786 小时前
页面内存只涨不跌? 一次泄漏排查, 牵出 WeakMap 的诞生
前端
Z小明6 小时前
第 6 章 组件进阶
前端·vue.js
江华森6 小时前
HTTP请求的完整过程详解:从DNS解析到TCP挥手的微秒级实战分析
前端