热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

webpack性能优化——CommonsChunkPlugin

前言:相信大家对webpack并不陌生,用webpack打包也是非常常见的事,但是webpack在打包的时候有很多配置可以对打包就行优化。最近正好在研究

前言:


相信大家对webpack并不陌生,用webpack打包也是非常常见的事,但是webpack在打包的时候有很多配置可以对打包就行优化。
最近正好在研究这方面的东西,所以在此记录一下,以便日后查看。



一、webpack-bundle-analyzer


在进入正文之前先说一个“好玩”的东西,是一个对webpack打包之后的文件进行分析的工具——webpack-bundle-analyzer



1. 安装

虽然是在webpack的配置文件中使用,但并不是webpack官方提供的插件,需要使用npm进行安装:

npm install webpack-bundle-analyzer --save-dev

2. 使用

首先在webpack的配置文件中引入webpack-bundle-analyzer,比如我的文件名是webpack.demo.config.js:

// webpack.demo.config.jsvar BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin

接着使用引入的BundleAnalyzerPlugin:

// webpack.demo.config.jsnew BundleAnalyzerPlugin({analyzerMode: 'server',analyzerHost: '127.0.0.1',analyzerPort: 8888,reportFilename: 'report.html',defaultSizes: 'parsed',openAnalyzer: true,generateStatsFile: false,statsFilename: 'stats.json',statsOptions: null,logLevel: 'info'
})

可以看到里面的参数还是很多的:


  • analyzerMode:表示已什么方式查看分析结果,可选参数为server, static or disabled

  • analyzerHost:analyzerModeserver的时候生效,表示启动http服务的IP地址。

  • analyzerPort:analyzerModeserver的时候生效,表示启动http服务的端口号。

  • reportFilename:analyzerModestatic的时候生效,表示输出静态文件的文件名,输出路径output路径相同。

  • defaultSizes:表示默认显示的数据模式,可选参数为stat, parsed or gzip

  • openAnalyzer:true|false,表示是否在打包完成之后自动打开分析界面。

  • generateStatsFile:true|false,表示是否生成.json文件。

  • statsFilename:设置generateStatsFiletrue的时候生成的.json文件名。

  • statsOptions:通过修改生成的.json文件中的source:false来排除模块的源码。

  • logLevel:日志的显示方式,可选参数为info, warn, error or silent


3. 效果

    无论是通过http服务还是通过打开静态文件的方式效果都是一样的:

基本分析图片

    从上面就可以看出上面的数据有三种,分别是defaultSizes的三个参数,由于我设置的是parsed所以默认显示parsed的大小。


简单解释一下defaultSizes三个参数的含义:
stat:是指打包之前的文件大小
parsed:是指打包之后的文件大小
gzip:是指通过gzip压缩之后的文件大小


    如果默认设置了parsed,但是我想看stat时候的文件大小视图改怎么办呢?
    当然可以在这个分析界面中去调整:

改变数据视图


4. 小结

    把最近看到的好东西拿出来分享一下,觉得使用这个东西一眼就能看出打包后的结构,每个模块分的很清晰,而且通过视图中每个模块占的面积大小很直观的能看出各个文件的体积比例,这对打包的分析很有帮助,并且使用简单,不需要进行什么复杂的配置。


二、CommonsChunkPlugin


接下来进入正题,就是这个webpack本身提供的插件 —— CommonsChunkPlugin

首先,介绍一下插件的使用格式;
然后,分析其中的每个参数的作用;
最后,举一个实际的“栗子”。



1. 介绍

    看到CommonsChunkPlugin这个名字,大概明白这个插件是跟公共模块有关系的。没错,这个插件就是用来提取出代码中公共的部分,并且将他们打包到一个单独的文件里面,这样就避免了重复打包。同时,由于配置中有minChunks(在文章后面会讲这个参数的作用)这个参数的存在可以满足一些其他的需求,不仅仅是提取公共部分这么简单了,而且一个文件中可以使用多次CommonsChunkPlugin插件。

    另外,还需要知道两个名词:chunkchunkName

    chunk:通过CommonsChunkPlugin生成的一个文件就是一个chunk,由于可能多次使用插件,所以每次打完包可能会很多chunk


注:如果是多入口,每一个入口文件都是一个chunk


    chunkName:上面说过每使用一次插件就会生成一个chunk,那这些chunk通过什么区分呢?答案就是chunkName


2. 使用

    由于是webpack提供的插件,所以就不需要安装了,直接在配置文件中引入,同样在此还是以webpack.demo.config.js为配置文件:

// webpack.demo.config.jsvar CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin")/*
* 省略其他代码
**/
new CommonsChunkPlugin({name: string, // ornames: string[],filename: string,minChunks: number|Infinity|function(module, count) -> boolean,chunks: string[],children: boolean,async: boolean|string,minSize: number,
})

or

当然,你也可以选择在头部一次引入webpack,以后内置的插件都可以通过webpack来使用,像这样:

// webpack.demo.config.jsvar webpack = require('webpack')/*
* 省略其他代码
**/
new webpack.optimize.CommonsChunkPlugin({name: string, // ornames: string[],filename: string,minChunks: number|Infinity|function(module, count) -> boolean,chunks: string[],children: boolean,async: boolean|string,minSize: number,
})

3. 参数

name|names:这里的name就是上面所说的chunkName,如果包括过个chunk,那么就使用names,以数组的形式传入chunkName,如:

names: ['vendor','utils']

filename:打包后的文件名,可以省略,如果省略默认文件名为name的值。

minChunks:定义提取公共部分的规则。


个人觉得这个minChunks是整个插件最屌的没有之一(自行忽略)。
如果值为数字,例:minChunks:2,就说明提取文件中最少被引用2次的代码,
如果值为Infinity,将会直接创建一个公共的chunk,但是里面没有模块,
如果值为函数,将会提取出满足函数条件的代码,生成一个公共chunk,所以可以在这里实现以下定制化的需求。函数会提供两个参数:modulecount


chunks:定义从哪些chunk中提取公共模块,如果省略,默认为入口chunk

children:默认是false,多个chunk里面的模块可能会有相同的依赖关系,如果设置为true,将其中相同的依赖提到父元素中(但是会影响初始加载的时间)。

async:异步加载的附加公共chunk, 当下载附加组块时,它会并行自动下载。

minSize:创建公共chunk之前,所有公共模块的的最小体积。


4. 实战


上面说了一堆理论,讲了一下基本结构,具体用法现在开始了!


下面是我一个Vue工程的项目结构:

项目结构

现在我想要提取出node_modules中以.js结尾的文件和src下以.vue结尾的文件,将他们分别打到两个文件中。

先看一下入口和出口文件:

entry: {main: './examples/main.js'
},
output: {path: path.resolve(__dirname, '../demo'),filename: '[name].[chunkhash].js',
}

接着,按照上面说的,我首先引入CommonsChunkPlugin:

var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin")

接着使用这个插件:

new CommonsChunkPlugin({name: "list",minChunks: function (module, count) {return (module.resource &&/\.js$/.test(module.resource) &&module.resource.indexOf(path.join(__dirname, '../node_modules')) === 0)}
}),
new CommonsChunkPlugin({name: 'components',chunks: ['main'],minChunks: function (module, count) {return (module.resource &&/\.vue$/.test(module.resource) &&module.resource.indexOf(path.join(__dirname, '../src')) === 0)}
}),
new CommonsChunkPlugin({name: "manifest",chunks: ['list', 'components']
})

打完包之后的结果是这样的,确实单独打出了两个文件:

Asset Size Chunks Chunk Names
components.8ec10c04b75e68ee707a.js 479 kB 1 [emitted] [big] componentsmain.a33511b70c4ad0a4aead.js 738 kB 2 [emitted] [big] mainlist.b2de50f4150e217815ca.js 789 kB 3 [emitted] [big] listmanifest.9412c3435bf535f63115.js 6.07 kB 4 [emitted] manifest

打包生成的文件目录结构是这样的:

demo结构

webpack-bundle-analyzer打开效果是这样的:

实战效果


5. 进阶


看着文档很简单,但是实际操作起来就有许多问题,比如:
- 打包之后Chunks那一列数字是什么?
- 出口文件中的chunkhash是什么?
- 生成manifest又是什么?
- minChunks函数中的参数到底有什么作用?


chunkhash

    首先,chunkhash既然叫hash,所以是一种hash值。当然,你也可以这么定义出口文件:

filename: '[name].[hash].js'

这里解释一下chunkhash与hash的区别:
- 对于打包生成的每个文件都有单独的hash值,这个hash值就叫做chunkhash;
- 而如果我们用[hash]定义出口文件,打包之后的文件hash值是一致的,因为这个hash是整个的hash值,我把出口文件改了之后打包生成的文件放在下面,可以跟上面打包后的文件对比一下;
- 所以,chunkhash与hash的区别就是私有hash与全局hash的关系。


Asset Size Chunks Chunk Names
components.26ae71410d030a4f8f66.js 479 kB 1 [emitted] [big] componentsmain.26ae71410d030a4f8f66.js 738 kB 2 [emitted] [big] mainlist.26ae71410d030a4f8f66.js 789 kB 3 [emitted] [big] listmanifest.26ae71410d030a4f8f66.js 5.98 kB 4 [emitted] manifest

manifest

    那么manifest又是什么呢?其实就是webpack的一个清单文件,manifest的作用就是将你之前打包好的每个文件的chunkhash利用webpack的缓存机制保存起来,如果下次没有修给这个chunk里面的文件,那你打包之后文件的chunkhash是不变的,修改过的会生成新的chunkhash
    接下来我修改上文中的其中一个.vue文件,在重新打包的结果是这样的,可以跟之前的对比一下,看是不是其他chunkhash没有变:

Asset Size Chunks Chunk Names
components.c2315d7bc104f905405c.js 479 kB 1 [emitted] [big] componentsmain.a33511b70c4ad0a4aead.js 738 kB 2 [emitted] [big] mainlist.b2de50f4150e217815ca.js 789 kB 3 [emitted] [big] listmanifest.e3e56878b56c560148b7.js 6.07 kB 4 [emitted] manifest

minChunks

    当minChunks为函数的时候,webpack会提供两个参数:modulecount。其中,module有两个属性module.contextmodule.resource:
    - module.resource:表示正在处理的文件位置(其实就是文件的路径)
    - module.context:表示文件所在的目录
    - count:表示文件被引用的次数


有兴趣可以把module.context和module.resource打印出来看一下。


对于count的使用其实很简单,这里我还是想提一下,直接把官网的栗子拿过来说:

new CommonsChunkPlugin({name: "list",minChunks: function (module, count) {// 这里就是说,将文件路径中存在somelib并且被引用了3次的文件// 如果说没有前面的条件,完全可以直接设置minChunks:3return module.resource && (/somelib/).test(module.resource) && count === 3}
}),

    到这里,上面写的CommonsChunkPlugin配置基本就很清晰了,但是对于打包之后的Chunks列数字问题,我在这里说一下,那些数字其实叫做Chunks.id,是自动生成的,从0开始。这时候细心的人发现我上面的打包结果中并没有0,是从1开始的,这是为什么呢?答案是:其实是有0的,只不过打出来的文件与本文并没有关系,所以让我手动把第一行给删了,不要纠结,就是从0开始的,没毛病。


6. 小节

上面就CommonsChunkPlugin的作用及配置进行了介绍,并且展示了一个小栗子,根据结果又分析出了很多东西。但是由于篇幅太长,配置里面的参数没有一一展示demo,如果想用可以自己再慢慢探索。


三、总结

    到这里文章就结束了,主要的目的还是为了记录和学习,顺便分享一下,以上都是亲自实践以及一些个人的理解,有兴趣的话也可以互相交流,交流是人类进步的阶梯。


推荐阅读
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 本文介绍了使用AJAX的POST请求实现数据修改功能的方法。通过ajax-post技术,可以实现在输入某个id后,通过ajax技术调用post.jsp修改具有该id记录的姓名的值。文章还提到了AJAX的概念和作用,以及使用async参数和open()方法的注意事项。同时强调了不推荐使用async=false的情况,并解释了JavaScript等待服务器响应的机制。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • Windows下配置PHP5.6的方法及注意事项
    本文介绍了在Windows系统下配置PHP5.6的步骤及注意事项,包括下载PHP5.6、解压并配置IIS、添加模块映射、测试等。同时提供了一些常见问题的解决方法,如下载缺失的msvcr110.dll文件等。通过本文的指导,读者可以轻松地在Windows系统下配置PHP5.6,并解决一些常见的配置问题。 ... [详细]
  • Firefox火狐浏览器关闭到http://detectportal.firefox.com的流量问题解决办法
    本文介绍了使用Firefox火狐浏览器时出现关闭到http://detectportal.firefox.com的流量问题,并提供了解决办法。问题的本质是因为火狐默认开启了Captive portal技术,当连接需要认证的WiFi时,火狐会跳出认证界面。通过修改about:config中的network.captive-portal-service.en的值为false,可以解决该问题。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • 本文总结了Java中日期格式化的常用方法,并给出了示例代码。通过使用SimpleDateFormat类和jstl fmt标签库,可以实现日期的格式化和显示。在页面中添加相应的标签库引用后,可以使用不同的日期格式化样式来显示当前年份和月份。该文提供了详细的代码示例和说明。 ... [详细]
  • 本文介绍了在rhel5.5操作系统下搭建网关+LAMP+postfix+dhcp的步骤和配置方法。通过配置dhcp自动分配ip、实现外网访问公司网站、内网收发邮件、内网上网以及SNAT转换等功能。详细介绍了安装dhcp和配置相关文件的步骤,并提供了相关的命令和配置示例。 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
author-avatar
成就未来7368
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有