去除无用的样式
安装: npm i purgecss-webpack-plugin glob -D
1 | // 去除无用的样式 |
下面我们来简单分析分析:
glob是用来查找文件的1
2
3
4glob.sync('./src/**/*', {nodir: true}
// 同步查找src目录下的任意文件夹下的任意文件
// 返回一个数组,如['真实路径/src/css/style.css','真实路径/src/index.js',...]
// {nodir: true}表示不包含文件夹,加快查找速度
purgecss-webpack-plugin是去除无用的css1
2
3
4
5new PurgecssWebpackPlugin({
// paths表示指定要去解析的文件名数组路径
// Purgecss会去解析这些文件然后把无用的样式移除
paths: glob.sync('./src/**/*', {nodir: true})
})
动态添加CDN
在html文件中引入cdn文件,在webpack配置externals,这样就不会打包引入的cdn的库
1 | // index.html文件 |
这样写完后,在js文件中我们就可以不用再导入jquery也能直接使用$操作符了
由于每次都需要在index.html模板中手动引入需要的cdn文件,然后还要在webpack里配置,有点繁琐了
So,html-webpack-externals-plugin这样的插件就应运而生了1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19// 动态添加CDN
const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin');
module.exports = {
plugins: [
new HtmlWebpackExternalsPlugin({
externals: [
{ // 引入的模块
module: 'jquery',
// cdn的地址
entry: 'https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js',
// 挂载到了window上的名称
// window.jQuery就可以全局使用
global: 'jQuery'
}
]
})
]
};
DllPlugin动态链接库
很多时候我们在开发时无论是用React还是Vue,我们都不希望这个开发的主力框架每次都被打包一遍,这样也是费时费力的事情
所以,出现了DllPlugin这种插件,它纯属webpack内置的,放心大胆的用
作用:
- 在第一次打包的时候就把打包用到的开发框架直接打包好,然后会生成一个manifest.json文件
- 再打包的的时候,只要有import React from ‘react’这样的引用,它就会先去所谓的缓存文件里找,找到了就直接用,也不用再进行对react打包了
- 如果没找到的话,再对框架打包一遍也无伤大雅
创建动态链接库
在根目录下创建一个webpack.dll.js文件,用来打包出dll文件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19const path = require('path');
// 引入webpack
const webpack = require('webpack');
module.exports = {
entry: ['react', 'react-dom'],
output: {
filename: 'react.dll.js',
path: path.resolve('dll'),
library: 'react' // 打包后被引用的变量名
},
plugins: [
// 动态链接库
new webpack.DllPlugin({
name: 'react',
path: path.resolve('dll', 'manifest.json')
})
]
};
代码写完了,npm run dll,之后会出现一个dll的文件夹,里面会包含你打包出来的文件
引用动态链接库1
2
3
4
5
6
7
8
9
10
11
12
13const path = require('path');
// 引入webpack
const webpack = require('webpack');
module.exports = {
plugins: [
// 引用对应的动态链接库的manifest.json文件
// 这样以后再引入react的时候就会优先在json文件里去寻找
new webpack.DllReferencePlugin({
manifest: path.resolve('dll', 'manifest.json')
})
]
};
写到这里还不算完,还需要在src目录下的index.html模板中引入一下1
<script src="../dll/react.dll.js"></script>
之所以,会新建一个dll目录,因为在npm start开发环境编译的时候,dist目录的内容都在内存中了,是找不到react.dll.js文件的
动态引入js
通过add-asset-html-webpack-plugin插件就可以完成这样的需求1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18// webpack.config.js文件
const webpack = require('webpack');
// 添加资源到html文件
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin');
module.exports = {
plugins: [
// 引用打包好的react,不会打包到bundle里
new webpack.DllReferencePlugin({
manifest: path.resolve('dll', 'manifest.json')
}),
// 直接将打包好的react.dll.js添加到html模板
new AddAssetHtmlWebpackPlugin({
filepath: path.resolve('dll', 'react.dll.js')
})
]
};
懒加载
说到懒加载必然是一种很好的优化网页或应用的方式,那么在webpack中也是通过ES6的import()语法来引入的。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26import React, { Component, Fragment } from "react";
import moment from "moment";
import "moment/locale/zh-cn";
// 设置中文
// moment.locale("zh-cn");
export default class List extends Component {
btnClick = () => {
import("./test").then((data) => {
console.log(data);
data.a();
});
};
render() {
console.log($);
let time = moment().format("YYYY-MM-DD HH:mm:ss");
return (
<Fragment>
<div>{time}</div>
<div>111</div>
<button onClick={this.btnClick}>222</button>
</Fragment>
);
}
}
抽取公共代码
比如有两个js文件,一个是index.js另一个是lrc.js,它们都引用了著名的实用工具库lodash,代码如下
1 | // index.js文件 |
抽取第三方模块1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// webpack.config.js文件
module.exports = {
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
chunks: 'initial',
minSize: 0,
minChunks: 2,
test: /node_modules/,
priority: 1
}
}
}
}
};
抽取公共模块1
2
3
4
5
6
7// index.js文件
import { flatten } from './common';
console.log('index',flatten([1,[33, 4, 5, [34]]]));
// lrc.js文件
import {flatten} from './common';
console.log(flatten([1,[33, 4, 5, [34]]]));
1 | // webpack.config.js文件 |
IgnorePlugin
作用: 忽略打包第三方模块指定的目录
为什么要忽略呢? 通过下面的栗子来看一下
相信很多人应该或多或少的都听过moment这个时间库,不知道也没关系,我来演示一波
先安装moment: npm i moment -S
1 | // index.js文件 |
页面上展示的一点毛病都没有,不过如果看一下打包的情况就会发现有瑕疵了
设置了中文,却把整个语言包都打包进去了,这样很不好
这是神马原因呢,其实是因为moment被导入的时候,附赠了整个locale语言包,这种买一赠一的行为就不用提现在代码世界了,吃不消了
我们需要用中文包,但是不想打包全部语言包,就让IgnorePlugin出马了1
2
3
4
5
6
7
8
9
10// webpack.config.js文件
const webpack = require('webpack');
module.exports = {
plugins: [
// 忽略moment目录下的locale文件夹
new webpack.IgnorePlugin(/\.\/locale/, /moment/)
]
};
配置改写后,再回到index.js中单独导入中文语言包就好了1
2
3
4
5
6
7
8
9
10// index.js文件
// 利用IgnorePlugin把只需要的语言包导入使用就可以了,省去了一下子打包整个语言包
import moment from 'moment';
// 单独导入中文语言包
import 'moment/locale/zh-cn';
let time = moment().endOf('day').fromNow();
window.root.innerHTML += time;
noParse
noParse的作用是不去解析你所使用的第三方库中的依赖库
1 | module.exports = { |
在工作中,忽略大型的库可以提高构建性能,可以从构建时间上看出来速度的提升,如上面代码中提到的jquery和lodash
resolve
从这个英文就能看出来,它就是配置模块如何解析用的,配置太多也没必要一一介绍了,还是直接说重点写出常用的配置吧
resolve常用配置
- modules
- 指定解析第三方包的目录位置
- alias
- 指定import导入时的别名,简化引入
- extensions
- 自动解析确定好的扩展名
- 默认会把js和json当做扩展名
1 | const { resolve } = require('path'); |
include和exclude
- include: 包含指定目录下的文件解析
- exclude: 排除指定目录不进行解析
二者使用一个即可了
1 | module.exports = { |
happypack
webpack在Node环境下运行所以也是单线程操作,一件一件的去处理事情。
于是乎,就有了happypack的用武之地了,它的作用就是可以实现多进程打包操作
1 | // webpack.config.js文件 |
由于HappyPack 对file-loader、url-loader 支持的不友好,所以不建议对该loader使用。
HappyPack 参数
- id: String 用唯一的标识符 id 来代表当前的 HappyPack 是用来处理一类特定的文件.
- loaders: Array 用法和 webpack Loader 配置中一样.
- threads: Number 代表开启几个子进程去处理这一类型的文件,默认是3个,类型必须是整数。
- verbose: Boolean 是否允许 HappyPack 输出日志,默认是 true。
- threadPool: HappyThreadPool 代表共享进程池,即多个 HappyPack 实例都使用同一个共享进程池中的子进程去处理任务,以防止资源占用过多。
- verboseWhenProfiling: Boolean 开启webpack –profile ,仍然希望HappyPack产生输出。
- debug: Boolean 启用debug 用于故障排查。默认 false。