noParse
针对没有AMD/CommonJS的源代码,通过配置noParse忽略webpack对其进行递归解析和处理,提高构建性能。比如jq,庞大又没有采用模块化标准,让webpack去解析是没有意义的。
noParse: /jquery/,// 不解析jquery中的依赖库
IgnorePlugin
忽略第三方包指定模块,使其不被打包进去。比如moment.js这个日期处理库,引用时会将所有的locale文件引入,导致打包体积比较大。可以通过webpack的IgnorePlugin,忽略locale下的文件,使用时只加载需要的语言包,较少打包体积
// webapck.config.s
plugins: [
new webpack.IgnorePlugin(/\.\/locale/, /moment/),
]
// index.js
import moment from 'moment';
import 'moment/locale/zh-cn'; // 主动引入所需语言包
moment.locale('zh-cn'); // 设置语言
let r = moment().endOf('day').fromNow();
console.log(r)
dllPlugin
DllPlugin: 即动态链接库插件,对于复用性较高的第三方模块,对其抽离打包到动态链接库中,再次构建时不需要重新打包此模块,只需重新打包业务代码,从而提升构建速度。 对于第三方模块,通过webpack进行打包后,需要定义一个变量来接收打包后的输出。可以通过library中指定这个变量
// webpack.config.react.js 实现动态链接库功能的webpack文件
let path = require('path');
let webpack = require('webpack');
module.exports = {
mode: 'development',
entry: {
react: ['react', 'react-dom'],
},
output: {
filename: '_dll_[name].js', // 产生的文件名
path: path.resolve(__dirname, 'dist'),
library: '_dll_[name]', // 导出值 如果生成的输出文件,是在HTML页面中作为一个 script 标签引入,则变量 '_dll_[name]'应与入口文件的返回值绑定。
libraryTarget: "window". // 配置如何暴露library,如果commonjs var this
},
plugins: [
new webpack.DllPlugin({
name: '_dll_[name]', // name和上面library的值对应
path: path.resolve(__dirname, 'dist', 'manifest.json'), // 生成manifest.json任务清单 根据清单查找对应文件
}),
],
};
// webpack.config.js 正式的webpack文件
plugins: [
new webpack.DllReferencePlugin({ // 打包时 根据manifest.json引用动态链接库中文件
manifest: path.resolve(__dirname, 'dist', 'manifest.json')
}),
],
// index.html引入打包好的文件
<body>
<div id='root'></div>
<script src="/_dll_react.js"></script>
</body>
在进行打包时,先根据manifest.json任务清单查找是否已经打包。如果在清单中没有找到,再去打包配置的第三方库。
Happypack
运行在Node.js上的webpack是单线程模型的,Happypack可以将文件解析任务分解成多个子进程并发执行,子进程处理完任务后再将结果发送给主进程,提升项目构件速度。
module: {
rules: [{
test: /\.js$/,
use: 'Happypack/loader?id=js', // 将原来的babel-loder等替换为happypack-loader,在插件中使用happypackLoader
exclude: /node_modules/,
}],
},
plugins: [
new Happypack({
id: 'js',
use: [{
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
'@babel/preset-react',
],
},
}],
}),
],
如果文件很小,是用多线程打包时速度可能更慢,因为分配现成也会花费一些时间
webpack自动优化
tree-shaking
用于描述移除JavaScript上下文中的未引用代码, 生产环境打包时,会自动移除js中未被引用代码,仅适用于import语法,require不支持。 在开发环境可以通过配置tree-shaking主动移除,
import calc from './test.js';
// let calc = require('./test.js'); // es6模块会把结果放在default上
console.log(calc.default.sum(1, 2));
scope-hosting 作用域提升
webpack的引入是把各个模块分开,通过__webpack_require__导入导出模块。scope-hosting可以把需要导入的文件直接移入导入者顶部,代码量明显减少,并且,不用多次使用__webpack_require__调用模块,运行速度也会得到提升。
let a= 1, b = 2, c = 3, d = 4;
let e = a + b + c + d;
console.log(e);
splitChunks抽离公共代码块
适用于多页应用,替换原来的commonChunkPlugins
optimization: {
splitChunks: {
cacheGroups: {
common: { // 对引用的公共模块抽离
minSize: 0, // 超过0个字节即进行抽离
minChunks: 2, // 公用次数超过2次即抽离
chunks: 'initial', //从入口开始
},
vendor: { // 将引用的第三方模块进行单独抽离
test: /node_modules/,
minSize: 0,
minChunks: 2,
chunks: 'initial',
priority: 1, // 指定权重, 先抽离第三方模块,在抽离common.否则会把第三方和其他代码抽离在同一个文件中
}
},
}
},
相关学习: zxc0328.github.io/2018/06/19/…
懒加载 @babel/plugin-syntax-dynamic-import
// webpack.config.js
module: {
rules: [{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
'@babel/preset-react',
],
plugins: [
'@babel/plugin-syntax-dynamic-import' // 使用懒加载的插件
],
},
},
}],
}
// index.js
let btn = document.createElement('button');
btn.innerHTML = 'hello';
btn.addEventListener('click', () => {
// es6草案中语法 通过jsonp实现动态加载文件,加载完返回一个promise
import('./source.js').then(data => {
console.log(data.default); // 结果挂载在default属性中
});
// console.log('click');
});
document.body.appendChild(btn);
热更新HMR
HotModuleReplacementPlugin允许在运行时更新所有类型的模块,而不需要完全刷新。不要在生产环境(production)下启用HMR。
devServer: {
hot: true, // 启动热更新
port: 3000,
open: true,
contentBase: './dist',
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html',
}),
new webpack.HotModuleReplacementPlugin(), // 热更新插件
new webpack.NamedModulesPlugin(), // 打印更新的模块路径
],
// index.js
import str from './source.js';
if (module.hot) { // 添加接收模块更新的代码
module.hot.accept('./source.js', () => {
let str = require('./source.js').default;
console.log(str, '文件更新了');
})
}