1:剔除npm包里面針對Node.js模塊自動引用的Polyfills
v4編譯引入npm包,有些npm包里面包含針對nodejs的polyfills,實際前端瀏覽器是不需要的
例如:
// index.js
import CryptoJS from 'crypto-js';
const md5Password = CryptoJS.MD5('123123');
console.log(md5Password);
v4 引入crypto-js模塊會自動引入polyfill: crypto-browserify, 但部分代碼是不需要的,v5 默認會自動剔除
v5編譯中,會出現(xiàn)polyfill添加提示,如果不需要node polyfille,按照提示 alias 設置為 false 即可
// webpack.config.js
resolve: {
// 1.不需要node polyfilss
alias: {
crypto: false
},
// 2.手動添加polyfills
// fallback: {
// "crypto": require.resolve('crypto-browserify')
// }
}
2:長期緩存優(yōu)化,
以前v4是根據(jù)代碼的結(jié)構(gòu)生成chunkhash,現(xiàn)在v5根據(jù)完全內(nèi)容生成chunkhash,比如改了內(nèi)容的注釋或者變量則不會引起chunkhash的變化,讓瀏覽器繼續(xù)使用緩存
1:moduleId改為根據(jù)上下文模塊路徑計算,chunkId根據(jù)chunk內(nèi)容計算
2: 為module,chunk 分配確定的(3或5位)數(shù)字ID,這是包大小和長期緩存之間的一種權(quán)衡
3:持久化緩存
1:第一次構(gòu)建是一次全量構(gòu)建,它會利用磁盤模塊緩存(以空間換時間),使得后續(xù)的構(gòu)建從中獲利。
2:后續(xù)構(gòu)建具體流程是:讀取磁盤緩存 -> 校驗模塊 -> 解封模塊內(nèi)容。
v5 默認情況,緩存配置是memory,修改設置為filesystem, 將緩存寫入硬盤
// webpack.config.js
module.exports = {
cache: {
// 1. 將緩存類型設置為文件系統(tǒng)
type: 'filesystem', // 默認是memory
// 2. 將緩存文件夾命名為 .temp_cache,
// 默認路徑是 node_modules/.cache/webpack
cacheDirectory: path.resolve(__dirname, '.temp_cache')
}
}
4: 模板聯(lián)邦
跨項目間的chunk可以相互共享
1:UMD 模塊
<script src="https://unkpg.com/lodash.js"></script>
2: 微前端:多個項目共存于一個頁面,有點類似iframe,共享的對象是項目級的,頁面級的
子應用間的chunk以及對象可通過全局事件共享,但是公共包在項目安置以及打包編譯很難放
子應用獨立打包,模塊解耦了,但公共的依賴不易維護處理
整體應用一起打包,能解決公共依賴;但龐大的多個項目又使打包變慢,后續(xù)也不好擴展
3:v5 的模塊共享
這個方案是直接將一個應用的 bundle,應用于另一個應用,動態(tài)分發(fā) runtime 子模塊給其他應用。
模塊聯(lián)邦的使用方式如下:
module.exports = {
// other webpack configs...
plugins: [
new ModuleFederationPlugin({
// 1. name 當前應用名稱,需要全局唯一
name: "app_one_remote",
// 2. remotes 可以將其他項目的 name 映射到當前項目中
remotes: {
app_two: "app_two_remote",
app_three: "app_three_remote"
},
// 3. exposes 表示導出的模塊,只有在此申明的模塊才可以作為遠程依賴被使用
exposes: {
AppContainer: "./src/App"
},
// 4. shared可以讓遠程加載的模塊對應依賴改為使用本地項目的 React或ReactDOM。
shared: ["react", "react-dom", "react-router-dom"]
}),
new HtmlWebpackPlugin({
template: "./public/index.html",
chunks: ["main"]
})
]
};
比如設置了remotes: { app_two: "app_two_remote" },在代碼中就可以直接利用以下方式直接從對方應用調(diào)用模塊
import { Search } from "app_two/Search";
app_two/Search來自于app_two 的配置:
// app_two的webpack 配置
export default {
plugins: [
new ModuleFederationPlugin({
name: "app_two",
library: { type: "var", name: "app_two" },
filename: "remoteEntry.js",
exposes: {
Search: "./src/Search"
},
shared: ["react", "react-dom"]
})
]
};
正是因為 Search在exposes被導出,我們因此可以使用 [name]/[exposes_name] 這個模塊,這個模塊對于被引用應用來說是一個本地模塊。
4:構(gòu)建優(yōu)化 — 更好的Tree Shacking
v4 有些場景是不能將無用代碼剔除的
1: 對于模塊引入嵌套場景,如下b 是不會出現(xiàn)在生產(chǎn)代碼里面的
// one.js
export const a = 1;
export const b = 2;
// two.js
import * as inner from "./inner";
export { inner }
// three.js
import * as module from "./module";
console.log(module.inner.a);
2:只有 test 方法使用了 someting 。最終可以實現(xiàn)標記更多沒有使用的導出項
import { something } from "./something";
function usingSomething() {
return something;
}
export function test() {
return usingSomething();
}
3: Commondjs?,F(xiàn)在Webpack不僅僅支持 ES module 的 tree Shaking,commonjs規(guī)范的模塊開始支持了
更細致的講解參考:
https://zhuanlan.zhihu.com/p/264826929
https://blog.csdn.net/P6P7qsW6ua47A2Sb/article/details/110015183
webpack dll: 將第三方庫打包成dll.js ,這樣修改應用代碼只會構(gòu)建應用的chunk,無關(guān)dll.js,加快速度,且瀏覽器緩存利好
https://www.cnblogs.com/skychx/p/webpack-dllplugin.html
hard-source-wepack-plugin:
https://segmentfault.com/a/1190000022453801
webpack 常用知識點
https://juejin.cn/post/6844904007362674701