Webpack 老项目的优化实践

大家好,我是前端架构师 ,关注微信公众号【程序员大卫】,免费领取精品前端资料。

背景

我将分享一些我在公司项目中实际操作的优化方法,最终使得项目的首屏加载速度显著提升。以下是优化前后的对比。

性能对比:

指标 优化前 优化后
JS 文件大小 32MB 4MB
首屏加载时间 12秒 2秒

从上面的对比可以看到,优化后项目加载速度有了质的飞跃,首屏加载时间从 11 秒降到了 1 秒,JS 文件的体积也减少了 80%以上。

优化步骤解析

接下来,我会详细讲解我在项目中实施的优化措施。

1. 分析打包体积,找出性能瓶颈

通过使用 webpack-bundle-analyzer 插件,我们可以直观地查看项目打包后各个文件的体积分布,并发现哪些模块占用了过多的空间。比如,element-plusecharts 等文件的体积非常庞大,这些文件直接影响了加载速度和构建时间。

可以使用按需加载 element-plus 组件,echarts 不要全局引入,按模块需要引入。

安装 webpack-bundle-analyzer 插件:

bash 复制代码
npm install webpack-bundle-analyzer -D

配置 webpack 以启用分析:

javascript 复制代码
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');

module.exports = {
  configureWebpack: {
    plugins: [
      new BundleAnalyzerPlugin()  // 用于展示各个模块的大小和依赖关系
    ]
  }
};

2. 使用cdn加载第三方js

使用 CDN 加速是常见的优化方式,它能显著减少项目的打包体积、提高页面加载速度并减少服务器带宽压力。

1. 将 CDN 资源提取到配置文件中

首先,你可以将 CDN 配置提取到一个独立的文件中(如 cdn-config.js),并在 vue.config.js 中动态加载。这种方式更灵活且易于维护,尤其是当项目有多个环境(开发、测试、生产)时。

cdn-config.js 示例:

javascript 复制代码
module.exports = {
  vue: 'https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.min.js',
  'element-ui': 'https://cdn.jsdelivr.net/npm/element-ui@2.15.0/lib/index.js',
  echarts: 'https://cdn.jsdelivr.net/npm/echarts@5.1.2/dist/echarts.min.js',
  css: {
    'element-ui': 'https://cdn.jsdelivr.net/npm/element-ui@2.15.0/lib/theme-chalk/index.min.css',
  },
};

2. 动态加载 CDN 链接

然后,在 vue.config.js 中动态加载这些 CDN 配置,并通过 chainWebpack 插入到 HTML 中。这种方式可以减少硬编码,提高可维护性,并且更灵活地切换 CDN。

vue.config.js 示例:

javascript 复制代码
const cdn = require('./cdn-config.js');
const isProduction = process.env.NODE_ENV === 'production';

module.exports = {
  configureWebpack: {
    externals: isProduction ? {
      vue: 'Vue',
      'element-ui': 'ELEMENT',
      echarts: 'echarts'
    } : {}
  },
  chainWebpack: config => {
    config.plugin('html').tap(args => {
      args[0].cdn = {
        js: Object.values(cdn).filter(url => url.endsWith('.js')),
        css: Object.values(cdn.css || {})
      };
      return args;
    });
  }
};

3. 在 HTML 模板中插入 CDN 资源

index.html 中,我们使用 html-webpack-plugin 插入 CDN 资源。通过 htmlWebpackPlugin.options.cdn 动态注入这些资源,使得 HTML 模板更加灵活,且无需硬编码每个 CDN 资源。

index.html 示例:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Webpack CDN Example</title>

  <!-- 动态插入 CSS -->
  <% for (var css of htmlWebpackPlugin.options.cdn.css) { %>
    <link rel="stylesheet" href="<%= css %>">
  <% } %>
</head>
<body>
  <div id="app"></div>

  <!-- 动态插入 JS -->
  <% for (var js of htmlWebpackPlugin.options.cdn.js) { %>
    <script src="<%= js %>"></script>
  <% } %>
</body>
</html>

4. 版本控制和 CDN 服务选择

使用 jsdelivrunpkg 这种公共 CDN 服务时,注意加上版本号,以确保兼容性。如果项目中有多个依赖项需要加载,最好选择那些稳定且提供长期支持的 CDN 服务,避免因为 CDN 服务问题导致的资源加载失败。

5. fallback 机制(备用方案)

为了保证 CDN 加载失败时,页面能正常工作,你可以为 CDN 资源提供一个 fallback 机制。当 CDN 资源无法加载时,可以从本地文件或其他备份源加载。

例如,在 HTML 中加一个简单的 fallback:

html 复制代码
<script>
  if (!window.Vue) {
    document.write('<script src="/path/to/local/vue.min.js"><\/script>');
  }
  if (!window.ELEMENT) {
    document.write('<script src="/path/to/local/element-ui.js"><\/script>');
  }
</script>

3. 懒加载优化

对于一些不常用的库或功能,我们可以通过懒加载来避免它们在首次加载时被下载。例如,Table2Excelexceljs 只是某些功能的依赖,并不会在页面加载时立刻用到。我们采用了 import() 异步加载这些模块。

javascript 复制代码
download() {
  import('table2excel.js').then((Table2Excel) => {
    new Table2Excel.default('#table').export('filename');
  });
}

通过这种方式,只有在需要时才会加载 Table2Excelexceljs,有效减轻了首次加载的压力。

4. 压缩并优化 Moment.js

Moment.js 是一个常用的时间处理库,但它的体积较大。我们通过忽略掉不必要的语言包,减少了它的体积。

vue.config.js 中配置:

javascript 复制代码
module.exports = {
  chainWebpack: config => {
    config.plugin('ignore')
      .use(new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/));  // 忽略 moment 的其他语言包
  }
};

然后在 main.js 中手动引入所需的语言包:

javascript 复制代码
import moment from 'moment';
import 'moment/locale/zh-cn';  // 只引入中文语言包
moment.locale('zh-cn');

这种做法将 Moment.js 的体积从几百 KB 降低到了 174KB。

5. Gzip 压缩文件

最后,为了进一步减小文件体积并提高加载速度,我们使用了 compression-webpack-plugin 插件对 JS 和 CSS 文件进行 Gzip 压缩。

javascript 复制代码
const CompressionPlugin = require('compression-webpack-plugin');

module.exports = {
  chainWebpack: config => {
    if (isProduction) {
      config.plugin('compressionPlugin').use(new CompressionPlugin({
        test: /\.(js|css)$/,  // 只压缩 JS 和 CSS 文件
        threshold: 10240,     // 压缩大于 10KB 的文件
        minRatio: 0.8,        // 压缩比率
        deleteOriginalAssets: true // 删除原始文件
      }));
    }
  }
};

经过这些优化,项目的打包文件大小从 3MB 减少到 860KB,加载速度得到了显著提升。

服务器端也得配置 nginx 开启静态压缩

总结

这些看似简单的优化方法,在实际应用中却能带来显著的性能提升。虽然这些优化技术不是什么新鲜事,但要在实际项目中实施却需要一定的时间和精力。

相关推荐
开利网络2 小时前
合规底线:健康产品营销的红线与避坑指南
大数据·前端·人工智能·云计算·1024程序员节
yinuo2 小时前
纯CSS&JS实现:丝滑渐变过渡的动态导航栏
前端
qq. 28040339842 小时前
vue介绍
前端·javascript·vue.js
未来之窗软件服务2 小时前
未来之窗昭和仙君(五十五)标签票据打印模板设计器——东方仙盟筑基期
前端·打印设计器·仙盟创梦ide·东方仙盟·昭和仙君·东方仙盟架构
Mr.Jessy2 小时前
Web APIs 学习第五天:日期对象与DOM节点
开发语言·前端·javascript·学习·html
前端大卫2 小时前
如何统一前端项目的 Node 版本和包管理器?
前端
Hi~晴天大圣3 小时前
HTML onclick用法
前端·html
!win !3 小时前
前端跨标签页通信方案(上)
前端·javascript
xw54 小时前
前端跨标签页通信方案(上)
前端·javascript