目錄
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哈'
效果演示: