簡介
Webpack4 那點兒東西 基於webpack4總結了一些webpack的常見配置,但是webpack 各種強大的配置有時候讓你不堪重負,會打包很多的檔案,遍歷解析很多檔案。。。。。總之,這些操作會讓webpack打包過程變得很慢,所以開發過程中我們不得不去優化一些配置,讓webpack更好的服務於我們的開發。
動態連結庫DLL
即把基礎模組的程式碼打包進入動態連結庫裡,比如常用的react,vue等,當需要匯入的模組在動態連線庫裡的時候,模組不能再次被打包,而是去動態連線庫裡獲取
- 建立一個webpack.dll.config.js檔案打包常用類庫到dll中
module.exports = {
entry: {
react: ['vue'] //vue模組打包到一個動態連線庫
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].dll.js', //輸出動態連線庫的檔名稱
library: '_dll_[name]' //全域性變數名稱
},
plugins: [
new webpack.DllPlugin({
name: '_dll_[name]', //和output.library中一致,也就是輸出的manifest.json中的 name值
path: path.join(__dirname, 'dist', '[name].manifest.json')
})
]
}
webpack --config webpack.dll.config.js --mode production
複製程式碼
- 在住配置檔案 webpack.config.js中加入以下程式碼
plugins: [
new webpack.DllReferencePlugin({
manifest: require(path.join(__dirname, 'dist', 'vue.manifest.json')),
})
]
webpack --config webpack.config.js --mode development
複製程式碼
這樣會從dll中獲取vue,而且不用再次打包vue了。
Webpack熱替換之HMR
Hot Module Replacement(以下簡稱 HMR)是 webpack 中超級有用的特性之一 ,當你對程式碼進行修改並儲存後,webpack 將對程式碼重新打包,並將新的模組傳送到瀏覽器端,瀏覽器通過新的模組替換老的模組,這樣在不重新整理瀏覽器的前提下就能夠對應用進行更新。從而減少很多時間。の。。。。比如,頁面中有一個modal框,需要點選button觸發modal顯示,在開發過程中,如果修改了modal 的樣式,觸發瀏覽器重新整理,你還需要再次點選button才能看到修改後的modal樣式,但是熱替換是不需要重新整理瀏覽器的,可以直接觀察到修改後的變化。 上文中已經介紹了watch的用法,但是watch是針對打包時檔案發生變化進行重新打包,而HMR是針對webpack-dev-server的。
- devserver配置如下
devServer: {//配置此靜態檔案伺服器,可以用來預覽打包後專案
inline:true,//打包後加入一個websocket客戶端
hot:true,//熱載入
contentBase: path.resolve(__dirname, 'dist'),//開發服務執行時的檔案根目錄
host: 'localhost',//主機地址
port: 9090,//埠號
compress: true//開發伺服器是否啟動gzip等壓縮
}
複製程式碼
- plugins配置項加入以下兩行
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin()//使用者名稱替代id
複製程式碼
3.業務程式碼中的修改
if(module.hot) {
module.hot.accept('./hello.js', function() {
div.innerHTML = hello()
})
}
複製程式碼
- 原理及流程解析大致流程: webpack-dev-server可以和瀏覽器之間建立一個web socket進行通訊,一旦新檔案被打包出來,webpack-dev-server就告訴瀏覽器這個訊息,這時瀏覽器就可以自動重新整理頁面或者進行熱替換操作。當一個模組b發生改變,而模組內又沒有HMR程式碼(類似於上述3中的程式碼)來處理這一訊息時,那這一訊息就會被傳遞到依賴模組b的其他模組上;如果訊息在新模組上沒有被捕獲的話就會再次進行傳遞;如果所有的訊息都被捕獲了的話,那我們的應用就應該已經按照程式碼進行了更新;反之如果有訊息冒泡到了入口(entry)檔案還沒有被捕獲的話,那就說明我們的程式碼中沒有處理這類變更方法,那webpack就會重新整理瀏覽器頁面,即從HMR回退到LiveReload。
Tree Shaking
tree shaking 是一個術語,通常用於描述移除 JavaScript 上下文中的未引用程式碼。這個術語和概念實際上是興起於 ES2015 模組打包工具 rollup。你可以將應用程式想象成一棵樹。綠色表示實際用到的原始碼和 library,是樹上活的樹葉。灰色表示無用的程式碼,是秋天樹上枯萎的樹葉。為了除去死去的樹葉,你必須搖動這棵樹,使它們落下。但是webpakc的Tree Shaking依賴靜態的ES6模組化語法即通過import和export匯入匯出的程式碼,而且需要引入一個能夠刪除未引用程式碼(dead code)的壓縮工具(minifier)(例如 UglifyJSPlugin)或者在執行命令的時候用webpack --display-used-exports --optimize-minimize --mode production
比如以下程式碼
export function getName() {
return 'hello world';
}
export function getAge() {
return 9999;
}
複製程式碼
如果你只引用了其中一個,那麼通過Tree Shaking會剔除另一個未用到的,打包的時候直接忽略。
{
test: /\.js/,
use: {
loader: 'babel-loader',
query: {
presets: ["env", {
+ modules: false //關閉 Babel 的模組轉換功能,保留原本的 ES6 模組化語法
+ }]
}
}
}
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
plugins: [
new UglifyJSPlugin()
]
webpack --display-used-exports --optimize-minimize
複製程式碼
提取公共程式碼
這個變化還是很大的,之前的webpack版本用的都是commonchunkplugin,但是webpack4開始使用common-chunk-and-vendor-chunk 配置如下:
optimization: {
splitChunks: {
cacheGroups: {
commons: {
chunks: "initial",
minChunks: 2,
maxInitialRequests: 5, // The default limit is too small to showcase the effect
minSize: 0 // This is example is too small to create commons chunks
},
vendor: {
test: /node_modules/,
chunks: "initial",
name: "vendor",
priority: 10,
enforce: true
}
}
}
}
複製程式碼
Scope Hoisting
作用域提升,這是在webpack3中所提出來的。它會使程式碼體積更小,因為函式申明語句會產生大量程式碼.
const ModuleConcatenationPlugin = require('webpack/lib/optimize/ModuleConcatenationPlugin');
plugins: [
// 開啟 Scope Hoisting
new ModuleConcatenationPlugin(),
],
複製程式碼
CDN
對於靜態資源的處理,放入CDN是一個很好的選擇,webpack中配置CDN的方式如下:
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name]_[hash:8].js',
publicPath: 'http://static.xxxx.com/'
},
複製程式碼
多程式之HappyPack
HappyPack就能讓Webpack把任務分解給多個子程式去併發的執行,子程式處理完後再把結果傳送給主程式,其中子程式的個數為cpu的個數減去1,需要在loader處修改如下
use: 'happypack/loader?id=babel',
複製程式碼
並且在plugin中新增以下程式碼:
new HappyPack({
id: 'babel',
//如何處理.js檔案,和rules裡的配置相同
loaders: [{
loader: 'babel-loader',
query: {
presets: [
"env", "stage-0"
]
}
}]
}),
複製程式碼
小結
以上為webpack配置中的一些常見優化方案,但是根據專案的不同,需要選擇的方案也不太一樣,多嘗試,根據特定的環境選擇特定的優化方案,我覺得是一件比較不錯的事情。