一、noParse
作用:不去解析三方模块中的依赖项目。
module:{
noParse: /jquery/, //不解析jquery中的依赖,节约打包时间
...
}
二、IgnorePlugin插件
作用:忽略三方包的指定目录,指定目录不会被打包进去。
很多教程都有介绍 moment。
我们在项目上做个试验,index.js 如下
import moment from 'moment'
let t = moment().endOf('day').fromNow()
console.log(t)
看下打包输出的index.js文件,so big!!!
我们看下moment.js 的加载依赖 加载了local文件下的所有语言包,实际开发一般只需要几种就可以了,因此IgnorePlugin插件
插件登场了。
let webpack = require('webpack')
plugins: [
new webpack.IgnorePlugin(/\.\/locale/,/monent/),
]
这个js是不是降了很多...接下来我们在index.js中引入需要的语言包,代码如下。
import moment from 'moment'
// 手动引入语言
import 'moment/locale/zh-cn'
// 设置语言
moment.locale('zh-cn')
let t = moment().endOf('day').fromNow()
console.log(t)
三、dllPlugin 插件实现动态链接库
动态链接库是比较重要的优化,当项目引用的三方库增多,打包的时间会大大增多(特别是热更新的时候),因此我们需要把三方库打包成动态链接库,我们还是以moment
为例。
- 1.重新创建一个
webpack.dll.config.js
打包三方库。
let path = require('path')
let webpack = require('webpack')
module.exports = {
mode:'development',
entry: {
moment:['moment'] // 打包的moment库
},
output: {
filename: "_dll_[name].js", // _dll_moment.js
path: path.resolve(__dirname,'dist/static'),
library: '_dll_[name]', // _dll_moment
libraryTarget: "var" // commonjs,var等输出类型
},
plugins: [
new webpack.DllPlugin({
name: "_dll_[name]",
path: path.resolve(__dirname,'dist/static','manifest.json')
}),
new webpack.IgnorePlugin(/\.\/locale/,/moment/),//这里去除local引用,上面已经介绍了
]
}
- 2.在
package.json
中创建npm
打包脚本
"dll": "webpack --config webpack.dll.config.js"
- 3.运行
npm run dll
看下输出。
- 4.在工程
webpack.base.js
创建对动态库的链接。
plugins: [
// new webpack.IgnorePlugin(/\.\/locale/,/moment/),
new webpack.DllReferencePlugin({
manifest: path.resolve(__dirname,'dist/static','manifest.json')
}),
...
]
- 5.在需要引用的
html
中加入script
引用。
<script src="./static/_dll_moment.js"></script> // 根据你的输出路径进行修改
- 6.运行
npm run build
看看效果,打包只有了3k+的大小。
五、happypack 多线程打包。
这个模块也是增加打包速度的,当项目依赖比较多的时候效果比较明显,这边就介绍下他的用法。
- 1.
npm i happypack -D
下载插件。 - 2.
webpack.base.js
代码
let HappyPack = require('happypack') //定义
module:{
{
test:/\.js$/,
use:'HappyPack/loader?id=js' //定义js使用happypack打包
},
{
test: /\.css$/, //正则匹配css文件
use: 'HappyPack/loader?id=css'//定义css使用happypack打包
},
...
}
plugins: [
// new webpack.IgnorePlugin(/\.\/locale/,/moment/),
// new webpack.DllReferencePlugin({
// manifest: path.resolve(__dirname,'dist/static','manifest.json')
// }),
new HappyPack({
id:'js',
use:[
{
loader: "babel-loader",
options: {
presets:[
'@babel/preset-env' //包含es6 转 es5模块
],
plugins:[
'@babel/plugin-proposal-class-properties'
]
}
}
]
}),
new HappyPack({
id:'css',
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader"
},
{
loader: "postcss-loader"
}
]
}),
...
]
执行npm run build
看下结果吧,开启了三个线程处理。
四、抽离公共代码
为了加深理解,我创建两个文件a.js
b.js
假设是工具js,在创建index.js
和test.js
都引用了上面两个文件。
a.js
console.log('a')
b.js
console.log('b')
index.js
import './a'
import './b'
console.log('index.js')
test.js
import './a'
import './b'
console.log('test.js')
然后在webpack.base.js
做如下配置
entry: {
index: path.resolve(__dirname,'src/index.js'),
test:path.resolve(__dirname,'src/test.js')
}, //入口
output: {
filename: '[name].js', // 默认是main.js 这里修改成index.js
path: path.resolve(__dirname,'dist') // 路径必须是一个绝对路径
},
执行npm run build
看下打包出的index.js和test.js文件,
很容易看出,这两个文件都引用了a.js、b.js!在多页开发中还是很影响性能的。
因此优化是需要把a.js和b.js抽离打包的,怎么做呢?我们需要在webpack配置如下代码。
optimization: {
splitChunks: {//分割代码块
cacheGroups: { // 缓存组
common:{ // 公共模块代码
minSize: 0, //文件大小大于0自己就抽离
minChunks: 2, // 引用两次抽离
chunks: "initial"// 从入口开始抽离
}
}
}
},
现在执行下npm run build
,已经抽离出来了。
optimization: {
splitChunks: {//分割代码块
cacheGroups: { // 缓存组
common:{ // 公共模块代码
minSize: 0, //文件大小大于0自己就抽离
minChunks: 2, // 引用两次抽离
chunks: "initial"// 从入口开始抽离
},
vendor:{
priority: 1, //优先抽离三方模块
test: /node_modules/, // 检测node_modules模块
chunks: "initial"// 从入口开始抽离
}
}
}
},
npm run build
看下输出,已经成功抽出了三方库。
小结:三方库的抽离还是需要看具体优化需求的,有时候dllPlugin动态链接方式结构会更清晰。
六、懒加载
懒加载的理解就是有需求的时候在加载资源文件
下面就给个需求说明下,我们点击按钮,动态加载js并执行,这里需要一个@babel/plugin-syntax-dynamic-import
,这里我已经安装了,只需要配置下。
use:[
{
loader: "babel-loader",
options: {
presets:[
'@babel/preset-env' //包含es6 转 es5模块
],
plugins:[
'@babel/plugin-proposal-class-properties',
'@babel/plugin-syntax-dynamic-import'
]
}
}
]
这个工程工程比较多,这边在重新创建一个source.js
,代码就写
module.exports = 'js被加载了'
index.html 中加入一个按钮事件
<button class="btn-danger btn" onclick="getUserAction()">提交</button>
index.js 中实现按钮点击动态加载source.js
let getUserAction = () =>{
import('./source').then(data => {
console.log(data.default)
})
}
window.getUserAction = getUserAction; //挂载到window上
现在直接npm run dev 看下结果
提交
按钮,动态加载了js并输出了结果。
七、webpack 热更新插件
webpack已经提供了热更新插件,这里只需要在开发模式下配置下即可。
let webpack = require('webpack')
devServer: {
hot:true,
...
}
plugins: [
new webpack.NamedModulesPlugin(),//打印热更新模块
new webpack.HotModuleReplacementPlugin(),//人更新插件
...
]
这里还是用第五节的source.js
进行修改热更新,index.js里面代码如下。
import str from './source'
console.log(str)
if (module.hot){
module.hot.accept('./source',()=>{
console.log('文件更新了')
})
}
当npm run dev
,对比发现,在没有配置热更新的时候,修改代码浏览器会刷新页面!配置了之后,只会修改相应的模块,并不会刷新页面。
源码下载
创建文件夹,cd至已创建文件夹,执行 git clone https://gitee.com/dolan_ge/webpack.git -b webpack_optimize
。
进入工程目录,执行 npm install -D
。