目录
1. dllPlugin :创建动态链接库
示例代码:
// index.js
import React from 'react';
import {render} from 'react-dom';
render(<h1>奶茶</h1>,window.root);
效果图:
上述是一个简单的React应用,打包情况如下:可以看出打包的文件有点大,那是因为webpack把引入的两个react文件也给打包进去了。
我们可以将react取出来打包,生成动态链接库:
创建webpack.config.react.js
配置文件,用来配置react打包生成动态链接库
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]',
// libraryTarget:'var' // 默认:var
},
plugins:[
new webpack.DllPlugin({ // 要求: name == library
name:'_dll_[name]',
path:path.resolve(__dirname,'dist','manifest.json')
})
]
}
打包后的目录结构:
打包生成的_dll_react.js
和manifest.json
(任务清单)文件
打包好后,如何引入?
在webpack.config.js
->plugins
中配置:
new webpack.DllReferencePlugin({
manifest:path.resolve(__dirname,'dist','manifest.json')
}),
注意:html模板文件需要写死,添加<script src='/_dll_react.js'></script>
最后,打包情况如下,文件小了很多,因为它没有打包react,而是引用已经打包好了的react文件;
2. happypack:实现多线程打包
安装:
npm i happypack
webpack.config.js
中配置:
let Happypack = require('happypack');
module
->rules
:
rules:[
{
test:/\.js$/,
exclude:/node_module/, // 排除目录
include:path.resolve('src'), //包含目录
use:'Happypack/loader?id=js'
}
]
plugins
:
new Happypack({
id:'js',
use:[{
loader:'babel-loader',
options:{
presets:[
'@babel/preset-env',
'@babel/preset-react'
]
}
}]
}),
上述配置使得.js
文件使用Happypack/loader
打包,调用下面id
为js
的Happypack
插件;
运行效果:可以看出打包使用了3个线程,用时1359ms;
注意:多线程打包过程中,多线程的运行也会消耗时间,需要打包的文件小的话,反而耗时更长;
css多线程打包同理:
{
test:/\.css$/,
use:'Happypack/loader?id=css'
}
new Happypack({
id:'css',
use:['style-loader','css-loader']
}),
3. webpack 自带优化
示例代码:
// test.js
let sum = (a,b) => {
return a+b+'sum';
}
let minus = (a,b) => {
return a-b+'minus';
}
export default {
sum,minus
}
// index.js
import calc from './test';
console.log(calc.sum(1,2))
上述代码下,当我们的webpack.config.js
里配置为:mode:'production',
生产环境下,minus
不会被打包进去;
注意:
import
在生产环境下,会自动去掉没用的代码 这个行为也称为tree-shaking
- es6模块会把结果放到
default
上,index.js
使用require
导入需如下,且不会自动去除无用代码// index.js const calc = require('./test'); console.log(calc.default.sum(1,2))
生产环境下,webpack
会自动省略可以简化的代码(scope hosting
),如下:
let a = 1;
let b = 2;
let c = 3;
let d = 4;
let e = a+b+c+d;
console.log(e);
4. 抽离公共代码
实现多页面的公共文件模块的抽离
这里index.js
和other.js
文件里都需要引用a.js
和b.js
;我们可以把a.js
和b.js
抽离出来;
webpack.config.js
配置:
optimization:{
splitChunks:{ // 分割代码块
cacheGroups:{ // 缓存组
common:{ // 公共模块
chunks:'initial', // 刚开始就需要进行抽离
minSize:0, // 大于0字节就抽离
minChunks:2 // 引用2次以上就抽离
}
}
}
},
common~index~other.js
就是抽离出来的文件,里面是a.js
和b.js
的内容,
如果在多个文件里引用了第三方模块比如:
import $ from 'jquery'
console.log($)
可以在webpack.config.js
中配置: vendor
部分配置抽离第三方模块
optimization:{
splitChunks:{ // 分割代码块
cacheGroups:{ // 缓存组
common:{ // 公共模块
chunks:'initial', // 刚开始就需要进行抽离
minSize:0, // 大于0字节就抽离
minChunks:2 // 引用2次以上就抽离
},
vendor:{
priority:1, // 设置权重,先抽离第三方模块
test:/node_modules/, // 引用了它,就抽离出来
chunks:'initial', // 刚开始就需要进行抽离
minSize:0, // 大于0字节就抽离
minChunks:2 // 引用2次以上就抽离
}
}
}
},
5. 懒加载
懒加载的实现:
目录:
示例代码:
通过内部的import
语句,生成1.index.js
文件,然后就可以调用这个文件
// index.js
let button = document.createElement('button');
button.innerHTML="按钮在此";
button.addEventListener('click',function() {
// es6 语法 jsonp实现动态加载文件
import('./source.js').then(data => {
console.log(data.default);
})
});
document.body.appendChild(button);
// source.js
export default '哈哈'
效果图:
6. 热更新
当模块被修改变动,只需加载更新模块,无需刷新重载整个页面;
webpack.config.js
中配置:
devServer:{
hot: true, // 启用热更新
port:3000, // 端口号
open:true, // 自动打开浏览器
contentBase:'./dist' // 用来指定被访问html页面的所在目录
},
plugins
中配置:
new webpack.NamedModulesPlugin(), // 打印更新的模块路径
new webpack.HotModuleReplacementPlugin() // 热更新插件
代码示例:
// index.js
import str from './source';
console.log(str);
if(module.hot){
module.hot.accept('./source',()=>{
let str = require('./source')
console.log(str)
})
}
// source.js
export default '哈1111哈'
效果演示: