上一節我們增加了一些高級特性的配置,地址
這一節,我們主要對構建性能進行優化,,
首先,我們祭出構建性能優化最強的工具,DllReferencePlugin,DllPlugin,
這個插件的主要功能是,對一些大的,不會經常變動的包,進行提前構建,打包出一個對某些模塊的映射文件和那些模塊的構建結果,然後在我們開發構建時,當引入那些包時,直接通過映射文件找到對應的打包好的文件而不需要再次打包,大大降低了構建速度,
簡單點說,就是提前打包好部分文件,
當你的項目依賴的變動小的文件很多時,這個方案可以是你的構建速度提高几個數量級,非常明顯,下面我們來介紹下插件的使用方法
這個插件是webpack自帶,不需要額外安裝,我們先額外創建一個配置文件,用來作爲提前構建的配置文件,webpack.dll.js
const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const webpack = require("webpack")
module.exports = {
entry: {
vendor:[
"vue",
"vue-router"
]
},
output: {
path: path.resolve(__dirname, 'static/js'),
filename: '[name].dll.js',
library:'[name]'
},
module:{
rules:[
{
test: /\.vue$/,
use:["vue-loader"]
},
{
test:/\.js$/,
use:["babel-loader"]
},
],
},
plugins:[
new VueLoaderPlugin(),
new webpack.DllPlugin({
path: path.join(__dirname, 'static/js', '[name]-manifest.json'),
name:"[name]"
})
]
}
需要提前構建的包,都可以放在entry下vendor數組裏,本例只引入了這兩個不需要變動的文件,順便貼下我們公司依賴的不需要變動文件
可以看到,如果開發環境下少打包這麼多文件,帶來的構建上的性能提升是巨大的。
我們在package.json中增加一個腳本專門用來打包提前構建的文件
"dll": "webpack --config webpack.dll.js"
按照上方配置文件,執行npm run dll
打包出一個vendor.dll.js和vendor-manifest.json文件到static/js文件夾下。
這時候,提前打包的文件已經打包好,我們可以通過任何方法把它引入到html文件中,我們通過最簡單的方式,直接通過script標籤,提前把它引入到index.html中
<script src="./static/js/vendor.dll.js"></script>
提前打包的文件已經打包好,映射文件也已經產生,這時,我們需要到webpack構建入口文件配置DllReferencePlugin插件來應用配置文件從而略過對已打包文件的打包過程
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require("./static/js/vendor-manifest.json"),
})
配置完成,
配置提前打包後,本例中,main.js
大小爲487kb,構建時間爲2500ms,配置前main.js
大小爲790kb,構建時間爲3400ms,可以看到,直接減少了一半的體積,一半的時間,性能提升非常明顯。
接下來,我們介紹提升構建性能的第二個有力工具,SplitChunksPlugin
在webpack4中,CommonsChunkPlugin已經被移除,替換爲SplitChunksPlugin,這個插件可以用於多頁面應用公共模塊的抽取和懶加載公共模塊的抽取,本例中我們是一個單頁面應用,但是用到了路由懶加載,當有很多路由時,SplitChunksPlugin帶來的構建性能的提升也是非常明顯的。
SplitChunksPlugin也是webpack4內置的插件,
optimization: {
splitChunks: {
name:'common',
minSize:1,
minChunks:1,
maxAsyncRequests:10,
chunks:'async'
},
},
把chunks設置爲async 表示只對懶加載的文件進行分割,minSize表示進行分割的最小體積,minChunks表示進行分割的模塊最小引入次數,maxInitialRequests表示入口文件不能同時懶加載文件的最高數量,如果超過就不進行分割,name表示分割後的名字,
然後我們在本例中額外增加兩個懶加載路由
import VueRouter from "vue-router"
export default new VueRouter({
routes:[
{
name:'routercomp',
path:'/',
component:() => import("../components/routercomp.vue")
},
{
name:'routercomp2',
path:'/2',
component:() => import("../components/routercomp2.vue")
},
{
name:'routercomp3',
path:'/3',
component:() => import("../components/rout.vue")
}
]
})
每個路由都引入一個dict模塊中的a變量
dict.js
export var a = 1
模塊routercomp.vue
,其他模塊類似
import {a} from "../static/lib/dict.js"
三個模塊都引入了dict
模塊中的a
變量,我們npm run dev
進行打包,
可以看到,打包出五個js文件,包括三個懶加載的路由文件,一個提取出的common文件,一個主入口main.js文件,三個路由文件中的公用模塊dict被打包到了common裏,避免了每個路由都重複dict模塊,降低了最終文件的大小,也降低了構建的速度。
接下來我們介紹下多進程打包
webpack4之前我們經常使用happypack進行多線程打包,充分利用多核cpu,然而,happypack的維護者,已經不在維護他,
Maintenance mode notice
My interest in the project is fading away mainly because I'm not using JavaScript as much as I was in the past. Additionally, Webpack's native performance is improving and (I hope) it will soon make this plugin unnecessary.
See the FAQ entry about Webpack 4 and thread-loader.
Contributions are always welcome. Changes I make from this point will be restricted to bug-fixing. If someone wants to take over, feel free to get in touch.
Thanks to everyone who used the library, contributed to it and helped in refining it!!!
並且,在webpack4上使用happypack和作者推薦的thread-loader並沒有明顯的性能提升,所以這兩個插件大家慎用,(懷疑webpack4已經內置多線程,單爲找到證據)
接下來我們介紹下對於一些耗時loader的優化
首先是babel-loader非常耗時,因爲無論是我們的工具js文件還是.vue中的script文件,最後都是會被babel-loader處理,所以對這個loader進行優化還是很有必要的,最簡單的優化方式便是爲babel-loader添加cacheDirectory屬性
{
test:/\.js$/,
use:["babel-loader?cacheDirectory=true"]
},
添加緩存屬性後,babel-loader的處理速度能夠提高2倍,在本例中,我們的啓動速度提高了兩倍以上。
對於其他的一些耗時loader我們可以使用cache-loader,對那些耗時loader進行緩存處理,但在本例中,沒有明顯提升,慎重使用。
最後介紹下webpack4 提供的模式配置
通過對mode的配置,webpack4會進行一些內置的優化,這也是在向配置簡單看齊,兩種模式webpack內置的優化如下
development
會將 process.env.NODE_ENV 的值設爲 development。啓用 NamedChunksPlugin 和 NamedModulesPlugin。
production
會將 process.env.NODE_ENV 的值設爲 production。啓用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 UglifyJsPlugin.
配置方式
mode:'development',
總結
這一節對webpack配置進行了優化,經過這些優化,無論我們的項目如何複雜,模塊如何多,webpack都不會對我們開發效率造成影響,本人實際項目中涉及150多模塊,引入衆多工具包,經過此配置的優化仍然保持熱更新在兩秒左右,開發效率未受到任何影響,
下一節我們將對生產環境進行配置,生產環境的需求和開發環境還是很不一樣的。
項目源碼在這裏,看的舒服的話順便給個star ><