webpack 优化笔记
webpack4 自带的优化包括 swingTree(摇摆树)和作用域提升
-
swingTree
比如入口文件 index.js引入通用方法 util, 里面有 10个方法, 通过 import只用到了两个。
那么剩余的 8个, 会剔除掉没有用到的死代码
util.js
function a() {} function b() {} function c() {} function d() {} export default { a, b, c, d }
index.js
import utils from './util' utils.a() utils.b()
webpack在构建的时候, 会把 c、d没用到的函数摇摆掉。 可以让 Webpack 打包出来的体积更小,运行更快。
webpack 配置的优化
- noParse
- exclude|include
- IgnorePlugin
- CDN
- Webpac.DllPlugin动态链接库
- optimization.splitChunks提取公用代码
- 懒加载(动态导入)
noParse
type: RegExp|[RegExp]|function
防止 webpack 解析那些任何与给定正则表达式相匹配的文件。忽略的文件中不应该含有 import、require等调用。
让 Webpack 忽略部分没有采用模块化文件的递归解析处理。被忽略的文件中不应该包含 import
、require
等模块化语句。
比如用到 jquery
这个库, 只是单纯的使用 jquery的API, 没有必要解析jquery
中的 import和require这些模块化语句。可以配置:
module.exports = {
module: {
// noParse: /jquery|lodash/,
// webpack.3.0.0支持函数
noPaese: content => /jquery|lodash/.test(content)
}
}
exclude|include
exclude: 表示哪些目录中的文件需要进行 loader转换
include: 表示哪些目录中的文件不需要进行 loader转换
比如使用 loader处理scss的时候, 我可以忽略的 node_modules中的, 只使用loader转换 src目录下的 scss文件的源码。
module.exports = {
module: {
rules: [
{
test: /\.scss$/,
exclude: /node_modules/, // node_modules中的scss文件不需要 loader转换
include: path.resolve(__dirname, 'src'), // src目录下的文件需要 loader转换
use: [
'style-loader',
'css-loader',
'sass-loader'
]
}
]
}
}
设置好exclude和include可以优化打包时间。
IgnorePlugin
IgnorePlugin 是 webpack自带的一个插件。 创建实例时可以传递两个参数
const webpack = require('webpack')
module.exports = {
plugins: [
new webpack.IgnorePlugin(requestRegExp, contextRegExp)
]
}
requestRegExp
: 匹配资源请求路径的正则表达式contentRegExp
: (可选的) 匹配资源上下文(目录)的正则表达式
根据 webpack官网给出的一个例子:
假如, 现在我项目中需要用到一个处理时间的库, 我选中了 moment时间库。
我通过 npm 安装 这个时间库, 它有一个语言包也一同下载到了 node_modules
目录下的moment/locale
文件夹中。 而这个时间库内部直接通过 require()引入了本地的这个时间库,而且超级大。100多个国家的语言,而我的项目中只需要zh-cn语言包就可以了。怎么办?
可以使用 IgnorePlugin这个插件,如下配置new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
第一个参数是构建的时候, 忽略通过 ./locale
引入的文件, 第二个参数是:引入的这个文件是在哪个目录下引入的。 而 ./locale
是再 moment
目录下的文件。
你可以通过手动按需引入你需要的语言包。 比如:
入口文件:
import zhCn from 'moment/locale/zh-cn.js'
CDN
CDN 又叫内容分发网络,通过把资源部署到世界各地,用户在访问时按照就近原则从离用户最近的服务器获取资源,从而加速获取资源的速度。
- HTML 文件不缓存,放在自己的服务器上,同时关闭服务器缓存。将HTML中的静态资源URL指向CDN服务器地址。
- 静态 JavaScript、CSS、图片等文件开启CDN和缓存,并且文件名带上 hash值
- 为了并行加载不阻塞, 把不同的静态资源分配到不同的CDN服务器
Webpack.DllPlugin动态链接库
地址链接
optimization.splitChunks提取公用代码
webpack4.x中使用 splitChunks取代了 CommonsChunkPlugin插件。
为什么要提取公用代码?
相同的资源(代码)被重复加载,浪费用户的流量和服务器成本。代码重复造成体积过大,影响首屏页面加载慢,影响用户体验。
优点:
将相同的代码块打包到一个文件,避免重复代码的加载,减少网络传输流量,降低服务器成本。
splitChunks 可以和 DLLPlugins一起使用时, mode
模式需要设置为 production
将多入口共用的代码提取为一个块。需要mode设为production
webpack配置
module.exports = {
mode: 'production',
entry: {
index: './src/index.js',
main: './src/main.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
// 配置splitChunks
// webpack 自带优化项
optimization: {
splitChunks: {
// 抽离
checkGroups: {
vendors: {
maxSize: 0,
chunks: 'inline',
minChunks: 2,
automaticNameDelimiter: '_',
}
}
}
}
}
运行 npx webpack, 除了生成 index.js
、main.js
,还会生成一份共用的代码块vendors_index_main.js
文件。
配置项:
cacheGroups: 自定义配置,主要使用它来决定生成的文件。
cacheGroups.test: 限制范围,主要是正则,匹配文件夹或文件。
name: 拆分块的名称,默认将根据块和缓存组键自动生成名称,上面是根据 vendors和入口文件的名称组和的。
priority: 优先级。
minSize: 要生成块的最小大小字节。 默认为 30000。可以设置为0。
minChunks: 指的是被不同的entry 引入的次数。如果为1时,适合分离第三方库node_modules。
automaticNameDelimiter: 拆分块名称的链接符,这里时_
,所以生成的块名称为 vendors_index_main.js
。
chunks: 这表示将选择哪些块进行优化。共有三个值 all
、initial
、async
。
-
initial
: 对于异步导入的文件不处理 -
async
: 只对异步导入的文件处理 -
all
: 全部chunk, 只要导入的文件都做处理
懒加载(动态导入)
懒加载即按需加载,很一种很好的优化网页和应用的方式。加快了应用的初始化加载速度,减轻了它们的总体积。
懒加载主要通过 import
方法引入模块。
webpack示例-> 这个是webpack官网上的例子
function getComponent() {
var element = document.createElement('div')
var button = document.createElement('button')
button.innerHTML = '按钮'
element.appendChild(button)
button.addEventListener('click', function () {
import(/* webpackChunkName: "print" */'./print')
.then(data => {
var print = data.default
print()
})
})
return element
}
document.body.appendChild(getComponent())
以上代码是当按钮被点击的时候,触发事件处理函数,通过import函数导入模块,并执行。