webpack打包优化实践

事情缘由

近段时间在做基于scratch3.0的改造项目。基于scratch-gui改造,项目本身已经很大了,然后里面还要用到scratch-blocks,scratch-vm,scratch-render等外部第三方项目。官方的配置是所有的东西打入一个lib中,所有的html都使用这一个lib。

现在有一个需求是:h5页面仅仅展示scratch做出来的作品,但是目前加载很慢,需要优化。

scratch原生的打包配置如下([email protected])

 

 打包结果全部js在lib.min中,有26M左右

 优化思路

第一阶段(不更改代码,仅仅做分包的优化):

  • 利用webpack optimization.splitChunks的vendors配置将所有的第三方包提取到vendors中【本人额外配置了一个所有入口都使用的第三方包bundle:‘vender.min'】;
  • 利用webpack optimization.splitChunks的default配置【默认的配置】自动提取各个入口js的共用代码组成bundle的功能
  • 分离出manifest文件,确保没有更改的包打包结果不会更改。

上面基本都利用了默认的配置【不配置的属性即使用默认值】,webpack默认的配置如下

module.exports = {
  //...
  optimization: {
    splitChunks: {
      chunks: 'async',
      minSize: 30000,
      maxSize: 0,
      minChunks: 1,
      maxAsyncRequests: 6,
      maxInitialRequests: 4,
      automaticNameDelimiter: '~',
      automaticNameMaxLength: 30,
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true
        }
      }
    }
  }
};
View Code

优化配置如下,

 打包结果如下:chunks中

其中vendors*.js 和 blocksonly~compatibilitytesting~gui~player.js即是默认的vendors和default配置提取出来的bundle。

是小了一点,但是项目还是太大了,特别是vendor.min.js。查看包发现工程引用的第三方模块中用到很多相同的模块

 解决办法:使用别名

resolve: {
        symlinks: false,
        extensions: ['.js', '.jsx', '.json'],
        alias: {
            // 别名,防止node_modules多个地方引入同样的包会打多份
            'scratch-l10n': path.resolve(__dirname, './node_modules/scratch-l10n'),
            'scratch-blocks': path.resolve(__dirname, './node_modules/scratch-blocks'),
            'scratch-render': path.resolve(__dirname, './node_modules/scratch-render'),
            'scratch-svg-renderer': path.resolve(__dirname, './node_modules/scratch-svg-renderer'),
            'scratch-audio': path.resolve(__dirname, './node_modules/scratch-audio'),
            'immutable': path.resolve(__dirname, './node_modules/immutable')
        }
    },

打包后结果

 小了3M。到目前为止,如果不更改代码基本已经无法再压缩了。

第二阶段:更改代码,一切与展示作品无关的东西都剥离后打包

  • 配置了公用vendors,避免默认的vendors(默认情况是不用更改的,本人的项目比较特殊,原因看后面的描述)
  • player代码和gui的代码分开,去掉player中不必要的代码引入

这一阶段player的代码进行精简,不和blocksonly / compatibilitytesting / gui公用一套代码。项目后面加上了一些hash.

由于项目中需要对scratch-blocks做更改,将scratch-blocks作为项目的git子模块。

不配置vendors则和默认配置等同,等同于如下代码

vendors配置如下:

 配置没有配置vendors和配置了vendors的对比(后面的就是配置了vendors)

 没有配置vendors,发现子模块scratch-blocks在多处打包,没有被提取出来。原因是我把scratch-blocks作为项目的子模块,不再是node_modules中的第三方模块。使用了别名配置

'scratch-blocks': path.resolve(__dirname, './scratch-blocks'),

默认的default配置貌似没法提取出来,可能原因是这个子模块的引用不像别的代码直接通过路径能找到,是通过scratch-blocks的package.json的main指定的【这个后面好好研究一下???】。

为了能提取这个scratch-blocks,本人便修改了vendors。去掉了只匹配“node_moddules”;只要三个以上chunks用到的模块都提取到vendors。

配置vendors打包后的结果可以看到,在网页端访问player页面,只需要引入三个js

vendor.min.938f6588ea10bb385ceb.js    7844K                                                        

vendors~blocksonly~compatibilitytesting~gui~player.b694ee6564cf5e22ed72.js   2998K

player.cb540c9b28aafd8d9503.js   95K

一共就10M多一点,比起之前要加载26M要好很多了。

 这里面有一个坑:按照webpack默认的default和vendors配置会自动提取公用代码生成新bundle,然后自动被html-webpack-plugin配置的html引用。但是,3.X的html-webpack-plugin如果不指定chunk,且在HtmlWebpackPlugin中显式配置chunk的名称,则不起作用。

比如:

 

 上面的vendors~blocksonly~***.js文件生成了,但是没有被引入到index.html代码中,导致访问index.html缺少这个文件直接展示不出来。

3.x的配置例子如下

 一旦指定splitChunks.name的名称,那么所有的入口必然引用这个bundle,无法生成各自入口的个性化bundle。所以建议升级html-webpack-plugin到4

纯属个人经验,有错误请大家多指正!

猜你喜欢

转载自www.cnblogs.com/chuaWeb/p/webpack-1.html