webpack优化之代码分割与公共代码提取的示例分析

发布时间:2021-06-26 14:59:06 作者:小新
来源:亿速云 阅读:186

小编给大家分享一下webpack优化之代码分割与公共代码提取的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

一、概念

在一切开始前,有必要先理清一下这三个概念:

二、问题分析

首先,简单分析下,我们刚才提到的打包问题:

弄明白了问题的原因,那么大致的解决思路也就出来了:

optimization.splitChunks

webpack提供了一个非常好的内置插件帮我们实现这一需求:CommonsChunkPlugin。不过在 webpack4 中CommonsChunkPlugin被删除,取而代之的是optimization.splitChunks, 所幸的是optimization.splitChunks更强大!

三、 实现

通过一个多页应用的小demo,我们一步一步来实现上述思路的配置。

demo目录结构:

|--public/
|   |--a.html
|   |--index.html
|--src/
|   |--a.js
|   |--b.js
|   |--c.js
|   |--index.js
|--package.json
|--webpack.config.js

代码逻辑很简单,index模块中引用了 a 和 b 2个模块,a 模块中引用了 c 模块和 jquery库,b 模块中也引用了 c 模块和 jquery 库,c 是一个独立的模块没有其他依赖。

index.js代码如下:

//index.js
import a from './a.js';
import b from './b.js';
function fn() {
 console.log('index-------');
}
fn();

a.js代码如下:

//a.js
require('./c.js');
const $ = require('jquery')
function fn() {
 console.log('a-------');
}
module.exports = fn();

b.js代码如下:

//b.js
require('./c.js');
const $ = require('jquery')
function fn() {
 console.log('b-------');
}
module.exports = fn();

c.js代码如下:

//c.js
function fn() {
 console.log('c-------');
}
module.exports = fn();

1. 基本配置

webpack先不做优化,只做基本配置,看看效果。项目配置了2个入口,搭配html-webpack-plugin实现多页打包:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
 entry: {
 index: './src/index.js',
 a: './src/a.js'
 },
 output: {
 path: path.resolve(__dirname, 'dist'),
 filename: '[name].js'
 },
 plugins: [
 new HtmlWebpackPlugin({
  template: './public/index.html',
  filename: 'index.html'
 }),
 new HtmlWebpackPlugin({
  template: './public/a.html',
  filename: 'a.html'
 })
 ]
}

在开发模式下运行webpack:

webpack优化之代码分割与公共代码提取的示例分析

可以看到,打包出两个html和两个体积很大的(300多K)的文件a.js,index.js。

进入dist目录检查js文件:

看,同样的代码c和jquery被打包了2遍。

2. 初步添加splitChunks优化配置

首先解决相同代码打包2次的问题,我们需要让webpack把c和jquery提取出来打包为公共模块。

在webpack配置文件添加splitChunks:

//webpack.config.js

optimization: {
 splitChunks: {
 cacheGroups: {
  default: {
  name: 'common',
  chunks: 'initial'
  }
 }
 }
}

- cacheGroups

- name

- chunks

再次打包:

webpack优化之代码分割与公共代码提取的示例分析

可以看到a.js,index.js从300多K减少到6点几K。同时增加了一个common.js文件,并且两个打包入口都自动添加了common.js这个公共模块:

webpack优化之代码分割与公共代码提取的示例分析

进入dist目录,依次查看这3个js文件:

发现,提是提取了,但是似乎跟我们预料的不太一样,所有的模块都跑到common.js里去了。

这是因为我们没有告诉webpack(splitChunks)什么样的代码为公共代码,splitChunks默认任何模块都会被提取。

- minChunks

splitChunks是自带默认配置的,而缓存组默认会继承这些配置,其中有个minChunks属性:

我们上面没有配置minChunks,只配置了name和chunk两个属性,所以minChunks的默认值 1 生效。也难怪所有的模块都被抽离到common.js中了。

优化一下,在缓存组里配置minChunks覆盖默认值:

//webpack.config.js

optimization: {
 splitChunks: {
  cacheGroups: {
   default: {
    name: 'common',
    chunks: 'initial',
    minChunks: 2 //模块被引用2次以上的才抽离
   }
  }
 }
}

然后运行webpack

webpack优化之代码分割与公共代码提取的示例分析

可以看到有2个文件的大小发生了变化:common.js由314K减小到311K,index.js由6.22K增大到7.56K。

进入dist目录查看:

a.js里依然不包含任何模块的代码(正常,因为a作为模块被index引入了一次,又作为入口被webpack引入了一次,所以a是有2次引用的)。

3. 配置多个拆分规则

3.1 实现代码分离,拆分第三方库

接下来,我希望公共模块common.js中,业务代码和第三方模块jquery能够剥离开来。

我们需要再添加一个拆分规则。

//webpack.config.js

optimization: {
 splitChunks: {
  minSize: 30, //提取出的chunk的最小大小
  cacheGroups: {
   default: {
    name: 'common',
    chunks: 'initial',
    minChunks: 2, //模块被引用2次以上的才抽离
    priority: -20
   },
   vendors: { //拆分第三方库(通过npm|yarn安装的库)
    test: /[\\/]node_modules[\\/]/,
    name: 'vendor',
    chunks: 'initial',
    priority: -10
   }
  }
 }
}

我给cacheGroups添加了一个vendors属性(属性名可以自己取,只要不跟缓存组下其他定义过的属性同名就行,否则后面的拆分规则会把前面的配置覆盖掉)。

- minSize

minSize设置的是生成文件的最小大小,单位是字节。如果一个模块符合之前所说的拆分规则,但是如果提取出来最后生成文件大小比minSize要小,那它仍然不会被提取出来。这个属性可以在每个缓存组属性中设置,也可以在splitChunks属性中设置,这样在每个缓存组都会继承这个配置。这里由于我的demo中文件非常小,为了演示效果,我把minSize设置为30字节,好让公共模块可以被提取出来,正常项目中不用设这么小。

- priority

priority属性的值为数字,可以为负数。作用是当缓存组中设置有多个拆分规则,而某个模块同时符合好几个规则的时候,则需要通过优先级属性priority来决定使用哪个拆分规则。优先级高者执行。我这里给业务代码组设置的优先级为-20,给第三方库组设置的优先级为-10,这样当一个第三方库被引用超过2次的时候,就不会打包到业务模块里了。

- test

test属性用于进一步控制缓存组选择的模块,与chunks属性的作用有一点像,但是维度不一样。test的值可以是一个正则表达式,也可以是一个函数。它可以匹配模块的绝对资源路径或chunk名称,匹配chunk名称时,将选择chunk中的所有模块。我这里用了一个正则/[\\/]node_modules[\\/]/来匹配第三方模块的绝对路径,因为通过npm或者yarn安装的模块,都会存放在node_modules目录下。

运行一下webpack:

webpack优化之代码分割与公共代码提取的示例分析

可以看到新产生了一个叫vendor.js的文件(name属性的值),同时common.js文件体积由原来的311k减少到了861bytes!

进入dist目录,检查js文件:

现在,我们在上一步的基础上,成功从common.js里把第三方库jquery抽离出来放到了vendor.js里。

3.2 拆分指定文件

如果我们还想把项目中的某一些文件单独拎出来打包(比如工程本地开发的组件库),可以继续添加拆分规则。比如我的src下有个locallib.js文件要单独打包,假设a.js中引入了它。

//a.js
require('./c.js');
require('./locallib.js'); //引入自己本地的库
const $ = require('jquery')
function fn() {
 console.log('a-------');
}
module.exports = fn();

可以这么配置:

//webpack.config.js

optimization: {
 splitChunks: {
  minSize: 30, //提取出的chunk的最小大小
  cacheGroups: {
   default: {
    name: 'common',
    chunks: 'initial',
    minChunks: 2, //模块被引用2次以上的才抽离
    priority: -20
   },
   vendors: { //拆分第三方库(通过npm|yarn安装的库)
    test: /[\\/]node_modules[\\/]/,
    name: 'vendor',
    chunks: 'initial',
    priority: -10
   },
   locallib: { //拆分指定文件
    test: /(src\/locallib\.js)$/,
    name: 'locallib',
    chunks: 'initial',
    priority: -9
   }
  }
 }
}

我在缓存组下又新增了一个拆分规则,通过test正则指定我就要单独打包src/locallib.js文件,并且把优先级设置为-9,这样当它被多次引用时,不会进入其他拆分规则组,因为另外两个规则的优先级都比它要低。

运行webpack打包后:

webpack优化之代码分割与公共代码提取的示例分析

可以看到新产生了一个locallib.js文件。进入dist目录查看:

现在我们又在上一步的基础上独立打包了一个指定的模块locallib.js。

至此,我们就成功实现了抽离公共模块、业务代码和第三方代码剥离、独立打包指定模块。

对比一下,优化前,打包出来js一共有633KB:

webpack优化之代码分割与公共代码提取的示例分析

优化后,打包出来js一共不到330KB:

webpack优化之代码分割与公共代码提取的示例分析

优化打包后的文件分类清晰,体积比优化前缩小了几乎50%,有点小完美是不是!击掌!这还只是我举的一个简单例子,在实际多页应用中,优化力度说不定还不止这么多。

小结

webpack很强大,以上只是冰山一角,但是只要掌握了上述optimization.splitChunks的核心配置,我们就可以几乎随心所欲地按照自己的想法来拆分优化代码控制打包文件了,是不是很酷?玩转代码拆分,你也可以!

如果觉得这些依然不能满足你的需求,还想更精(bian)细(tai)地定制打包规则,可以到webpack官网查看optimization.splitChunks的更多配置。

以上是“webpack优化之代码分割与公共代码提取的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!

推荐阅读:
  1. 如何分析Webpack代码分离
  2. Webpack 4教程:为什么要优化代码

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

webpack

上一篇:PHP_FE宏替换过程是怎样的

下一篇:Android中怎么设置屏幕大小

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》