Webpack进阶配置
1.多入口打包
首先多入口打包,必须指定两个入口文件,两个入口路径
接着配置出口,出口就是name + 对应 contenthash值。
由于多入口,出口肯定也有多个,出口的filename肯定不能够写死
另外有关于入口的相关插件也需要根据不同入口配置多个
像上面的HtmlWebpackPlugin 作用就是对入口js生成相应的入口html(webpack不会生成,必须装这个插件,否则前端页面写好的都没html入口挂载js文件)
2.抽离css
如果这部分不处理,不抽离css的话,用原来的style loader 会把css 和 js 打包到一起。在生产环境下,包过大肯定是不行的
为什么不用style loader:这是由于style loader作用是把当前页面的样式表打到当前页面的js当中,我们打开页面的时候,解析出样式文件对应的js,然后解析出样式,用一个style标签放到当前的html head 中
而MiniCssExtractPlugin 里面的loader,它可以把css抽离成单独的文件,打包时,用一个link标签,链接到抽离的样式表文件中,等到看页面的时候用link标签css文件
将style loader 替换为MiniCssExtractPlugin.loader
然后再用MiniCssExtractPlugin 指定css的存放文件
最后配置这两个插件,压缩css文件的体积
3.提取公共代码
提取公共代码则是使用熟悉的splitChunks。
配置公共代码,和第三方模块的缓存组,比如说下面的vendor,vendor 就是第三方库的一个拆分的包,可以把所有第三方库都打进这个vendor之中,可以指定minSize,就是从多少大小开始打包,如果minsize设置30000的话,那么就是说超过30kb的都打进vendor 这个js文件中。
当然可以针对庞大的第三方库单独进行打包,比如echarts,可以单独设置一个缓存组,让他一个文件打成几个vendor,减小加载一个过大文件的压力
最后,在入口的htmlPlugin中,还要考虑最终的代码分割,可以指定这个html拥有哪些chunk,
如果没用到某个chunk,比如我把echars 打成一个chunk,某个入口用不到,那么没必要加载,就可以在chunks里面指定chunk。
4.多进程打包与压缩
这个不多赘述,只需要两个插件即可
happyPack,多进程打包插件
ParallelUglifyPlugin:多进程压缩
注意点:如果项目较小,使用多进程打包反而拖慢速度,因为别的进程也需要性能支出
5.如何避免打包无效代码或减少代码体积
1.使用cdn引入的方式,注意,一旦使用cdn之后,开发环境肯定不能用cdn引入,也就是cdn要与node_modules 库文件共存,这样才便于开发,不然使用cdn全局引入,开发者可能都不知道当前使用的函数,或者是类来自哪个库,接着。在打包时,配置external,这样就会把第三方库排除出去,最终上线版本没有第三方库,直接使用cdn全局代码
注意点:cdn引入有一个注意点,对于引入cdn时,我们可以只写引入的路径,然后域名相关内容,我们可以通过output配置下的 publicPath进行设置
2.使用ignorePlugin,这个插件可以避免某个库的打包,比如一个第三方库,有一个函数永远不可能用到,为了避免一些开发者使用全量引入,导致把不需要的包打进来,那么就可以使用ignorePlugin去指定哪些库的指定内容不打包进来
3.mode:producetion, 自动开启treeShaking,去掉无用代码
注意点:只有esmoudle的代码支持treeShaking,CommonJS是不支持的,这是因为esmoudle 的静态分析,在代码执行之前就进行一次预编译,在这个预编译分析阶段可以实现treeShaking优化.
6.scope Hoisting
scope Hoisting,作用域提升,也就是将分散的js文件,打包成一个js,他会静态的分析文件,找到依赖关系,将依赖的内容放到一个文件中执行,这大大减少了文件数量,也适当减少代码体积,当然,由于又要分析代码,所以这玩意也只能通过esmoudle 才能够实现
7.babel
babel 其实就是做语法转义的,它可以将高语法转换为低语法,比如说将es6 转成es5 的语法
1.基本配置:
presets,也就是配置预设的插件,@babel/preset-env, 是babel核心库,里面继承了大部分语法转意的插件,底下useBuiltIns,usage,代表按需引入语法转移插件,先分析代码用了哪些语法,然后再引入对应插件,corejs 代表配置 pollyfill 的版本,
2.插件配置,插件就是用来处理语法转换过程中的部分问题,最常用的插件就是babel-runtime。
我们知道,如果一个语法,老版本浏览器没有,我们做pollyfill,肯定是在原来的内容上挂载新的方法,比如一个浏览器不支持promise,那么使用babel 之后,会在浏览器的window上重写一个promise方法,然后挂载进去,假如说这个我的使用的某个库也对window上进行了操作,挂载了一个promise,那么使用babel之后肯定把前面的promise 给覆盖了,那么babel-runtime,使用这个插件就可以避免问题,直接把挂载函数名改成一个独特的名字,比如window.__promise__, 调用primise方法时调用__promise__ 即可