#每天都是崭新的一天#再累也要照顾好自己

webpack提取公共代码,提取基础库,提取业务公共代码

一、前言

大型站点开发中,有很多个页面组成,但是SPA单页面应用中。所有页面都使用相同技术栈,以及同一套样式代码,导致页面之间有很多相同代码。

如果每一个页面都把公共的部分包含进去,会出现问题:

(1)相同资源被重复加载,浪费用户的流量和服务器的成本。

(2)每个页面都需要加载的资源大,首屏渲染速度变慢,影响用户体验。

比较好的实践:用户第一次访问,页面的公共代码被浏览器缓存起来,用户切换到其他页面,存放公共代码的文件不会被重新加载,而是直接从缓存中获取,优势:

(1)减少网络请求,降低服务器压力。

(2)第一次用户打开网站得不到优化,但是访问其他页面速度大大提升。


二、如何提取公共代码原理

在实际开发中如何进行提取代码,有提取基础库代码,有提取业务依赖相同代码。可以参照以下原则:

(1)根据开发中使用的技术栈,找到网站所有页面需要用到的基础库。,放在一个base.js文件中。

(2)再找出页面业务都依赖的公共部分代码提取出来,放在一个common.js文件中。

(3)再为每一个网页生成单独文件,不包含上面两个js文件。


有个疑问?

为啥已经抽离了comon.js,为啥还需要再抽离base.js?

原因:为了能够长期缓存base.js文件。只要不升级基础库版本,base.js就不会变,hash值不会被更新,缓存不会被更新,因为base.js通常比较大,网站提速。


三、如何通过webpack提取公共代码

1、抽离commonjs

webpack内置了专门用于提取多个Chunk中公共部分的插件commonChunkPlugin。

使用方法:

const CommonsChunkPlugin = require('webpack/lib/optimize/CommonChunkPlugin');
new CommonsChunkPlugin({
    chunks: ['a', 'b'],     //从哪些chunk中提取
    name: 'common'    // 提取公共部分形成一个新的chunk
})

以上配置就是从网页a和网页b中抽离公共部分,放到common中。

每个CommonsChunkPlugin实例中生成一个新的chunk,这个新的chunk包含被提取出来的代码,使用中必须制定name属性。

运行打包之后,会得到四个文件:

base.js:所有网页都依赖的基础库组成的代码;
common.js:网页A、B都需要的,但又不在 base.js 文件中出现过的代码;
a.js:网页 A 单独需要的代码;
b.js:网页 B 单独需要的代码。


2、抽离basejs

首先需要配置一个chunk,这个chunk只依赖所有页面的都依赖的基础库react,react-dom,为了基础运行库从common中抽离到base中

首先一个base.js文件

import 'react';
import 'react-dom';

import './base.css'

接着在修改webpack配置,entry中加入base。

module.exports = {
    entry: {
       base: './base.js'
    }
}

这就完成了新chunk的base设置。

从commonjs中提取base,还需要配置一下CommonsChunkPlugin,相关设置:

new commonsChunkPlugin({
   chunks: ['common', 'base'],    // 从common和base两个chunk中抽取公共部分
   name: 'base'   // 把公共部分方法放到base中
})


四、webpack4.0之后的optimization

webpack4官方开始移除commonChunk插件,改用optimization属性的配置。

1、为啥废弃commonsChunkPlugin,而引入optimization.splitChunks和optimization.runtimeChunk?

答:主要是为了优化chunk的拆分。

commonsChunkPlugin的思路:将满足minChunks配置所设置的条件模块移到一个新的chunk文件中,思路是父子关系。新生成的chunk是所有chunk的父亲,在加载子chunk的时候,父亲chunk是必须提前加载的。

产生一些问题:

(1)产生chunk在引入的时候,会包含重复的代码。

(2)无法优化异步的chunk。

(3)高优的chunk产出需要minchunks配置比较复杂。

optimization.splitChunks思路是:引入chunkGroup概念,如下图所示:


runtimeChunk作用呢?

之前commonChunkPlugin会把webpack runtime的基础函数提取出来,单独做一个chunk,webpack4开始采用runtimeChunkPlugin将每个entry chunk中的runtime部分函数分离出来,只需要简单配置:

optimization.runtimeChunk: true



2、optimization包含常用配置

(1)minimize

如果mode是priduction类型,minimize的默认值为true,执行默认压缩。

(2)minimizer

如果想使用第三方压缩,可以使用optimization.minimizer的数组列表中进行配置

(3)splitChunksPlugin

看一个简单例子

splitChunks: {
    chunks: "async”,//默认作用于异步chunk,值为all/initial/async/function(chunk),值为function时第一个参数为遍历所有入口chunk时的chunk模块,chunk._modules为chunk所有依赖的模块,通过chunk的名字和所有依赖模块的resource可以自由配置,会抽取所有满足条件chunk的公有模块,以及模块的所有依赖模块,包括css
    minSize: 30000,  //表示在压缩前的最小模块大小,默认值是30kb
    minChunks: 1,  // 表示被引用次数,默认为1;
    maxAsyncRequests: 5,  //所有异步请求不得超过5个
    maxInitialRequests: 3,  //初始话并行请求不得超过3个
   automaticNameDelimiter:'~',//名称分隔符,默认是~
    name: true,  //打包后的名称,默认是chunk的名字通过分隔符(默认是~)分隔
    cacheGroups: { //设置缓存组用来抽取满足不同规则的chunk,下面以生成common为例
       common: {
         name: 'common',  //抽取的chunk的名字
         chunks(chunk) { //同外层的参数配置,覆盖外层的chunks,以chunk为维度进行抽取
         },
         test(module, chunks) {  //可以为字符串,正则表达式,函数,以module为维度进行抽取,只要是满足条件的module都会被抽取到该common的chunk中,为函数时第一个参数是遍历到的每一个模块,第二个参数是每一个引用到该模块的chunks数组。自己尝试过程中发现不能提取出css,待进一步验证。
         },
        priority: 10,  //优先级,一个chunk很可能满足多个缓存组,会被抽取到优先级高的缓存组中
       minChunks: 2,  //最少被几个chunk引用
       reuseExistingChunk: true,//  如果该chunk中引用了已经被抽取的chunk,直接引用该chunk,不会重复打包代码
       enforce: true  // 如果cacheGroup中没有设置minSize,则据此判断是否使用上层的minSize,true:则使用0,false:使用上层minSize
       }
    }
}




文章转载:网络
感谢你的阅读,本文由 sau交流学习社区 版权所有。
如若转载,请注明出处:sau交流学习社区-power by saucxs(程新松)(/page/822.html)
交流咨询
    官方QQ群
    群号663940201,欢迎加入!
    sau交流学习社区交流群

微信群
欢迎加入微信群
微信公众号
欢迎关注微信公众号

图文推荐

微信群
saucxs聊天机器人
saucxs
hi ,欢迎来到sau交流学习社区,欢迎与我聊天,问我问题哦!
您正在使用的浏览器是,不在支持范围内!
为了您的正常使用与展示,推荐使用Chrome浏览器68以上版本
支持浏览器:
火狐浏览器最新版
Safari浏览器最新版
Edge浏览器最新版
IE浏览器10,11