前言
这是我花了几个星期学习 webpack4 的学习笔记。内容不够细,因为一些相对比较简单的,就随意带过了。希望文章能给大家带来帮助。如有错误,希望及时指出。例子都在learn-webpack仓库上。如果你从中有所收获的话,希望你能给我的github
点个star
。
tree shaking
一个模块里会导出很多东西。把一个模块里没有被用到的东西都给去掉。不会把他打包到入口文件里。tree shaking 只支持 es6 的方式引入(import
),使用require
无法使用tree shaking
。
webpack
的development
无法使用tree shaking
功能。除非在打包的配置里加上
1 | // 开发环境需要加如下代码 |
当你需要 import 某个模块,又不想tree shaking
把他给干掉,就需要在 package.json 里修改sideEffects
参数。比如当你import './console.js'
, import './index.css'
等没有export
(导出)模块的文件。又不想tree shaking
把它干掉。
1 | // package.json |
在development
环境即使你使用tree shaking
,它也不会把其他多余的代码给干掉。他只会在打包的文件里注明某段代码是不被使用的。
development
和 production
区别
development
代码不压缩,production
代码会压缩
省略…☺
webpack-merge
react
和vue
都会区分环境进行不同的webpack
配置,但是它们一定会有相同的部分。这个时候需要通过使用webpack-merge
进行抽离。
1 | // webpack.base.config.js |
这里就不重复把production
环境在配置出来了,主要介绍下webpack-merge
用法。
安装
npm i webpack-merge -D
新建一个公共的文件如:
webpack.base.config.js
将
development
和production
两个webpack
配置相同的抽离到webpack.base.config.js
文件中在环境配置文件中(具体代码如上)
const merge = require('webpack-merge')
const baseConfig = require('./webpack.base.config.js')
module.exports = merge(baseConfig, devConfig)
code splitting
和splitChunks
当你把所有的代码都打包到一个文件的时候,每次改一个代码都需要重新打包。且用户都要重新加载下这个 js 文件。但是如果你把一些公共的代码或第三方库抽离并单独打包。通过缓存加载,会加快页面的加载速度。
- 异步加载的代码,webpack 会单独打包到一个 js 文件中
- 同步加载的代码有两种方式
原始代码
1 | import _ from 'lodash'; |
打包后的文件:
main.js 551 KiB main [emitted] main
可以看到,webpack 将业务代码跟 lodash 库打包到一个 main.js 文件了
方法一:
创建一个新文件
1 | import _ from 'lodash'; |
将文件挂载到window
对象上,这样其他地方就可以直接使用了。
然后在 webpack 配置文件中的 entry 增加一个入口为该文件。让该文件单独打包。
1 | Asset Size Chunks Chunk Names |
方法二:
通过添加optimization
配置参数
optimization
: 会将诸如lodash
等库抽离成单独的chunk
,还会将多个模块公用的模块抽离成单独的chunk
1 | optimization: { |
打包后文件:
1 | Asset Size Chunks Chunk Names |
可以看到,webpack 将 lodash 抽成公共的 chunk 打包出来了。
splitChunks
里面还可以在添加个参数cacheGroups
1 | optimization: { |
cacheGroups
中vendors
配置表示将从node_modules
中引入的模块统一打包到一个 vendors.js 文件中
splitChunks
的vendors
的default
参数:
根据上下文来解释,如上配置了vendors
,打包node_modules
文件夹中的模块,
那么default
将会打包自己编写的公共方法。
当不使用default
配置时。
1 | Asset Size Chunks Chunk Names |
添加如下配置之后:
1 | optimization: { |
打包后的文件体积为
1 | Asset Size Chunks Chunk Names |
配置说明
1 | splitChunks: { |
Lazy Loading
异步import
的包会被单独打成一个chunk
1 | async function getComponent() { |
chunk
每一个js
文件都是一个chunk
chunk
是使用Webpack
过程中最重要的几个概念之一。在 Webpack 打包机制中,编译的文件包括 entry(入口,可以是一个或者多个资源合并而成,由 html 通过 script 标签引入)和 chunk(被 entry 所依赖的额外的代码块,同样可以包含一个或者多个文件)。从页面加速的角度来讲,我们应该尽可能将所有的 js 打包到一个 bundle.js 之中,但是总会有一些功能是使用过程中才会用到的。出于性能优化的需要,对于这部分资源我们可以做成按需加载。
打包分析
打包分析:
安装:npm install --save-dev webpack-bundle-analyzer
1 | // package.json => scripts |
1 | // webpack.config.js |
执行命令npm run analyz
浏览器就会自动打开localhost:8888
,分析图就会展现在你眼前
非常清晰直观的看出
![image-20190421142354243](/Users/zhouatie/Library/Application Support/typora-user-images/image-20190421142354243.png)
CSS 文件的代码分割
我们之前写的 css 文件都会被打包进 js 文件中,要想把 css 单独打包成一个 css 文件该怎么做呢?
这个时候就需要用到MiniCssExtractPlugin
开发环境用不到这个功能,一般都是用在生产环境中。
安装:npm install --save-dev mini-css-extract-plugin
1 | // webpack.config.js |
这样打包之后,css 会被单独打包成一个 css 文件。
缓存
目前为止,我们每次修改内容,打包出去后的文件名都不变。线上环境的文件是有缓存的。所以当你文件名不变的话,更新内容打包上线。有缓存的电脑就无法获取到最新的代码。
这个时候我们就会用到contenthash
我们先记录配置contenthash
之前打包的文件名。
1 | Asset Size Chunks Chunk Names |
接下来我们来配置下contenthash
(就是根据你文件内容生成的 hash 值)
1 | // webpack.config.js |
打包完之后会在main
后面接上hash
值。
1 | Asset Size Chunks Chunk Names |
当你不更新内容重新打包后,contenthash
还会维持不变。所以线上用户访问的时候就不会去服务器重新拿取代码,而是从缓存中取文件。
shimming
(预置依赖)
以jquery
为例,代码如下
1 | // index.js |
当你不在 test.js 中引入import $ from 'jquery'
那么浏览器访问的时候,会报
test.js:5 Uncaught ReferenceError: $ is not defined
这个时候就需要使用垫片功能
1 | const webpack = require('webpack'); |
当你加上这段代码后,模块在打包的时候,发现你使用了$
就会在你模块顶部自动加入import $ from 'jquery'
其他关于shimming
的内容参考webpack
官网 shimming