小帅の技术博客 小帅の技术博客
首页
  • 基础
  • 框架
  • 进阶
  • 工程化
  • NodeJS
  • 脚本
  • 拓展
  • 技术
  • 服务器
程序猿
关于
友链
  • 分类
  • 标签
  • 归档
GitHub

前端小帅

学而不思则罔,思而不学则殆
首页
  • 基础
  • 框架
  • 进阶
  • 工程化
  • NodeJS
  • 脚本
  • 拓展
  • 技术
  • 服务器
程序猿
关于
友链
  • 分类
  • 标签
  • 归档
GitHub
  • 基础

  • 工程化

    • 搭建一个标准化react+ts项目
    • Webpack项目优化系列一
      • CDN加速
        • 方式一
        • 方式二
      • Gzip配置
      • splitChunks 拆包优化
    • 【rollup】Svelte框架初尝试
    • 【rollup】构建发布一个npm包
    • 【vite】构建标准化react应用
    • 【vite】构建vue3+ts应用
    • 【前端组件化】系列第一篇
    • 【前端组件化】系列第二篇
  • 框架

  • 精进

  • 其他

  • 前端
  • 工程化
sunss
2020-09-27

Webpack项目优化之CDN加速、Gzip压缩和SplitChunks拆分

提示

这里以vue项目为例,配置包括但不限于vue项目。其他项目按类似逻辑配置即可。

# CDN加速

  • 分析:通过把类似 echart、element-ui、lodash 等第三方依赖库单独提取出,从而减小打包的体积大小,关键属性 externals 配置后的依赖插件不会被打包进 chunk 。而使用 CDN 加速、缓存也能加快访问速度。

  • 操作:这里我们主要通过 chainWebpack 中配置 externals 进行处理。

  • 提醒: 对于 externals 中的 key 和 value 如何确定的问题,可以参考这篇文章 Vue项目中CDN的配置

  • 免费CDN:unpkg 、jsdelivr ,其他服务自行考虑。

# 方式一

在 index.html 中手动引入 cdn 链接。

vue.config.js 配置文件:

const IS_PRO = process.env.NODE_ENV === 'production';
module.exports={
  //... 其他基本配置
  chainWebpack: (config) => {
    if (IS_PRO) {
      config.externals({
          echarts: 'echarts'
      });
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11

public/index.html 文件:

  <div id="app"></div>
  <!-- 推荐放在 <div id="app"></div> 后面 -->
  <script src="https://cdn.jsdelivr.net/npm/echarts@4.8.0/dist/echarts.min.js"></script>
1
2
3

# 方式二

通过 html-webpack-plugin 将 cdn 注入到 index.html 之中

  • 介绍:html-webpack-plugin 的作用是当使用 webpack打包时,创建一个 html 文件,并把 webpack 打包后的静态文件自动插入到这个 html 文件当中。html-webpack-plugin 默认将会在 output.path 的目录下创建一个 index.html 文件, 并在这个文件中插入一个 script 标签,标签的 src 为 output.filename。

  • html-webpack-plugin 的具体使用可以参考这篇文章 html-webpack-plugin 使用总结

vue.config.js 中的 html-webpack-plugin 配置

const cdn={
  css:[],
  js:['https://cdn.jsdelivr.net/npm/echarts@4.8.0/dist/echarts.min.js']
}
// 通过 html-webpack-plugin 将 cdn 注入到 index.html 之中
config.plugin('html').tap(args=>{
  args[0].cdn=cdn
  return args
})
1
2
3
4
5
6
7
8
9

# Gzip配置

文档地址:CompressionWebpackPlugin

vue.config.js 通过插件 html-webpack-plugin 配置

const IS_PRO = process.env.NODE_ENV === 'production';
const CompressionPlugin = require('compression-webpack-plugin');
const productionGzipExtensions = ['js', 'css'];
module.exports={
  //... 其他基本配置
  configureWebpack: (config) => {
    if (IS_PRO) {
        //gzip压缩
        config.plugins.push(
            new CompressionPlugin({
                //asset、algorithm默认值为[path].gz[query]、gzip
                // asset: '[path].gz[query]',
                // algorithm: 'gzip',
                // filename:'',
                test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
                threshold: 10240,
                minRatio: 0.8
            })
        );
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

不过要使用扩展名为 .gz 的预压缩文件也需要web服务器(如 nginx )进行对应的配置,可以参考这篇文章 nginx 配置 gzip_static

nginx支持 静态压缩 和 动态压缩,对于项目中已有 .gz 文件可以使用静态压缩, 而对于项目中没有已编译的 .gz 文件,可以采用动态压缩利用 nginx gzip 功能,需要对应模块 ngx_http_gzip_static_module 支持。

这里推荐 nginx 动态压缩 和 静态压缩 结合使用会更好:

# 开启和关闭gzip模式
gzip on;
# gizp压缩起点,文件大于1k才进行压缩
gzip_min_length 1k;
# 设置压缩所需要的缓冲区大小,以4k为单位,如果文件为7k则申请2*4k的缓冲区 
gzip_buffers 4 16k;
# 设置gzip压缩针对的HTTP协议版本
gzip_http_version 1.0;
# gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间
gzip_comp_level 2;
# 进行压缩的文件类型
gzip_types text/plain application/javascript text/css application/xml;
# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# splitChunks 拆包优化

  • 分析:webpack 默认配置下会把所有的依赖和插件都打包到 vendors.js 中,有些可能是 app.js 。所以,对于大量引入第三方依赖的项目,这个文件会非常的大。而对于在特定页面中才会使用的插件也会造成性能浪费。这时拆分和异步就显得尤为重要了。

  • webpack-bundle-analyzer:包的大小本地打包完成时可以看到,若想更仔细的分析可以通过插件 webpack-bundle-analyzer ,使用方法可以参考这篇文章 webpack-bundle-analyzer插件快速入门

  • SplitChunksPlugin:具体参数和细节可以参考这篇文章 webpack SplitChunksPlugin实用指南

vue.config.js 配置文件:

const IS_PRO = process.env.NODE_ENV === 'production';
module.exports={
    chainWebpack: (config) => {
        config.when(IS_PRO, (config) => { //when 也可以换成 if
            //拆包
            config.optimization.splitChunks({
                chunks: 'all',
                cacheGroups: {
                    //这里会继承splitChunks下的配置和默认配置,如 上面的 chunks:"all"
                    //下面的配置优先级更高,会覆盖上面的配置,如 chunks:"initial"
                    //因为 webpack4 的零配置,会有很多默认配置,所以对于细节和实际未知的项目编译结果时,务必确定并理解默认值的具体逻辑,以排查问题所在。(之前踩过不少坑~)
                    libs: {
                        name: 'chunk-libs', //包名称,会和hash值编译生成最终 chunk-libs.8880c0aa.js (hash值会变化,对于缓存优化这里是可以思考的一个点。)
                        test: /[\\/]node_modules[\\/]/, // 正则过滤依赖包
                        priority: 10, //设置包的打包优先级
                        chunks: 'initial' //all 、async、initial
                    }
                    vantUI: {
                        name: 'chunk-vantUI',
                        priority: 20,
                        test: /[\\/]node_modules[\\/]_?vant(.*)/
                    },
                    echarts: {
                        name: 'chunk-echarts',
                        priority: 20,
                        test: /[\\/]node_modules[\\/]_?echarts(.*)/
                    },
                    commons: {
                        name: 'chunk-commons',
                        test: resolve('src/components'),
                        minChunks: 3,
                        priority: 5,
                        reuseExistingChunk: true
                    }
                }
            });
        });
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

可以看看最终结果,已经很理想了,压缩后的 gzip 也是非常的小了,非常的nice~ ✨

更多玩法自行探索,也欢迎一起交流 🔥

splitChunks

编辑
#webpack
上次更新: 2024/04/15, 14:35:14
搭建一个标准化react+ts项目
【rollup】Svelte框架初尝试

← 搭建一个标准化react+ts项目 【rollup】Svelte框架初尝试→

最近更新
01
说说call、apply、bind是如何改变this的
03-29
02
从输入 URL 到页面加载完成发生了什么?
03-29
03
JavaScript进阶—— new 的执行过程
03-26
更多文章>
sunss | © 2020.08-2024.04 浙ICP备2022002957号-1
载入天数... 载入时分秒...  |  总访问量 次
提供CDN加速/云存储服务
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式