前端打包优化分析

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

相关推荐
yinuo15 分钟前
前端跨页面通讯终极指南⑧:Cookie 用法全解析
前端
小鑫同学16 分钟前
vue-pdf-interactor 技术白皮书:为现代 Web 应用注入交互式 PDF 能力
前端·vue.js·github
GISer_Jing27 分钟前
Nano Banana:AI图像生成与编辑新标杆
前端·javascript·人工智能
gyx_这个杀手不太冷静40 分钟前
上线前不做 Code Review?你可能正在给团队埋雷!
前端·代码规范·团队管理
全栈老石1 小时前
从硬编码到 Schema 推断:前端表单开发的工程化转型
前端·vue.js·架构
weixin_462446231 小时前
【原创实践】使用 shell 脚本批量创建 Linux 用户并生成随机密码
linux·服务器·前端
软件技术NINI1 小时前
娃娃店html+css 4页
前端·css·html
wordbaby2 小时前
TanStack Router 路径参数(Path Params)速查表
前端
盟接之桥2 小时前
盟接之桥--说制造:从“找缝隙”到“一万米深”——庖丁解牛式的制造业精进之道
大数据·前端·数据库·人工智能·物联网·制造
巴拉巴拉~~2 小时前
Flutter 通用滑块组件 CommonSliderWidget:单值 / 范围 + 刻度 + 标签 + 样式自定义
开发语言·前端·javascript