前言javascript
平常開發中,Vue框架一般都會使用Webpack進行構建,隨着項目不斷迭代,項目逐漸變得龐大,然而項目的構建速度隨之變得緩慢,因而對Webpack構建進行優化變得刻不容緩。經過適當的方法優化後,項目的構建速度提升了50%。現將相關優化方法進行總結分享。css
一.優化loader配置html
因爲Loader對文件的轉換操做很耗時,因此須要讓儘量少的文件被Loader處理。咱們能夠經過如下3方面優化Loader配置:(1)優化正則匹配(2)經過cacheDirectory選項開啓緩存(3)經過include、exclude來減小被處理的文件。實踐以下:前端
項目原配置:vue
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test')]
},複製代碼
優化後配置:
java
{
// 1、若是項目源碼中只有js文件,就不要寫成/\.jsx?$/,以提高正則表達式的性能
test: /\.js$/,
// 2、babel-loader支持緩存轉換出的結果,經過cacheDirectory選項開啓
loader: 'babel-loader?cacheDirectory',
// 3、只對項目根目錄下的src 目錄中的文件採用 babel-loader
include: [resolve('src')]
},複製代碼
二.優化UglifyJS插件node
webpack默認提供了UglifyJS插件來壓縮JS代碼,可是它使用的是單線程壓縮代碼,也就是說多個js文件須要被壓縮,它須要一個個文件進行壓縮。因此說在正式環境打包壓縮代碼速度很是慢(由於壓縮JS代碼須要先把代碼解析成用Object抽象表示的AST語法樹,再去應用各類規則分析和處理AST,致使這個過程耗時很是大)。webpack
所以咱們須要能夠並行處理多個子任務,多個子任務完成後,再將結果發到主進程中,有了這個思想後,所以 ParallelUglifyPlugin 插件就產生了,當webpack有多個JS文件須要輸出和壓縮時候,原來會使用UglifyJS去一個個壓縮而且輸出,可是ParallelUglifyPlugin插件則會開啓多個子進程,把對多個文件壓縮的工做分別給多個子進程去完成,可是每一個子進程仍是經過UglifyJS去壓縮代碼。無非就是變成了並行處理該壓縮了,並行處理多個子任務,效率會更加的提升。ios
安裝 webpack-parallel-uglify-plugin 插件web
而後在webpack.config.js 配置代碼以下:
// 引入 ParallelUglifyPlugin 插件const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');module.exports = { plugins: [ // 使用 ParallelUglifyPlugin 並行壓縮輸出JS代碼 new ParallelUglifyPlugin({ // 傳遞給 UglifyJS的參數以下: uglifyJS: { output: { /* 是否輸出可讀性較強的代碼,即會保留空格和製表符,默認爲輸出,爲了達到更好的壓縮效果, 能夠設置爲false */ beautify: false, /* 是否保留代碼中的註釋,默認爲保留,爲了達到更好的壓縮效果,能夠設置爲false */ comments: false }, compress: { /* 是否在UglifyJS刪除沒有用到的代碼時輸出警告信息,默認爲輸出,能夠設置爲false關閉這些做用 不大的警告 */ warnings: false, /* 是否刪除代碼中全部的console語句,默認爲不刪除,開啓後,會刪除全部的console語句 */ drop_console: true, /* 是否內嵌雖然已經定義了,可是隻用到一次的變量,好比將 var x = 1; y = x, 轉換成 y = 5, 默認爲不 轉換,爲了達到更好的壓縮效果,能夠設置爲false */ collapse_vars: true, /* 是否提取出現了屢次可是沒有定義成變量去引用的靜態值,好比將 x = 'xxx'; y = 'xxx' 轉換成 var a = 'xxxx'; x = a; y = a; 默認爲不轉換,爲了達到更好的壓縮效果,能夠設置爲false */ reduce_vars: true } } }), ]}複製代碼
打包對比基本上大小能相差30%!!!!
三.減小冗餘代碼
babel-plugin-transform-runtime 是Babel官方提供的一個插件,做用是減小冗餘的代碼 。 Babel在將ES6代碼轉換成ES5代碼時,一般須要一些由ES5編寫的輔助函數來完成新語法的實現,例如在轉換 class extent 語法時會在轉換後的 ES5 代碼裏注入 extent 輔助函數用於實現繼承。babel-plugin-transform-runtime會將相關輔助函數進行替換成導入語句,從而減少babel編譯出來的代碼的文件大小
四.DllPlugin分包
經過DllPlugin
插件分離出第三方包
新建webpack.dll.conf.js
const path = require('path');
const webpack = require('webpack');
const CleanWebpackPlugin = require("clean-webpack-plugin");
module.exports = {
entry: {
vendor: [
'vue',
'vue-router',
'vuex',
'axios',
'element-ui',
'echarts'
]
},
output: {
filename: '[name]_dll_[hash:6].js', // 產生的文件名
path: path.resolve(__dirname, '../static/dll'),
library: '[name]_dll_[hash:6]'
},
plugins: [
new CleanWebpackPlugin({
root: path.resolve(__dirname, '../static/dll'),
dry: false // 啓用刪除文件
}),
new webpack.DllPlugin({
name: '[name]_dll_[hash:6]',
path: path.resolve(__dirname, '../static/dll', '[name].dll.manifest.json')
})
]
};複製代碼
修改webpack.prod.conf.js
使用add-asset-html-webpack-plugin
動態添加dll.js
到html
。
須要注意
add-asset-html-webpack-plugin
要在HtmlWebpackPlugin
後引入;
html-webpack-plugin
依賴包版本4.0.0-alpha
會出個問題,添加上去的路徑會變成undefined
須要是3.2.0版本
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');
...
plugins: [
// 插入dll json
new webpack.DllReferencePlugin({
context: path.join(__dirname),
manifest: require('../static/dll/vendor.dll.manifest.json')
}),
new HtmlWebpackPlugin(),
// 插入 dll js
new AddAssetHtmlPlugin([{
publicPath: config.build.assetsPublicPath + 'static/dll/', // 注入到html中的路徑
outputPath: 'static/dll/', // 輸出文件目錄
filepath: resolve('static/dll/*.js'), // 文件路徑
includeSourcemap: false,
typeOfAsset: "js"
}])
]複製代碼
五.按需加載代碼
經過vue寫的單頁應用時,可能會有不少的路由引入。當打包構建的時候,javascript包會變得很是大,影響加載。若是咱們能把不一樣路由對應的組件分割成不一樣的代碼塊,而後當路由被訪問的時候才加載對應的組件,這樣就更加高效了。這樣會大大提升首屏顯示的速度,可是可能其餘的頁面的速度就會降下來。
項目中路由按需加載(懶加載)的配置:
const Foo = () => import('./Foo.vue')
const router = new VueRouter({
routes: [
{ path: '/foo', component: Foo }
]
})複製代碼
六.提取公共代碼
若是每一個頁面的代碼都將這些公共的部分包含進去,則會形成如下問題 :
• 相同的資源被重複加載,浪費用戶的流量和服務器的成本。
• 每一個頁面須要加載的資源太大,致使網頁首屏加載緩慢,影響用戶體驗。
若是將多個頁面的公共代碼抽離成單獨的文件,就能優化以上問題 。Webpack內置了專門用於提取多個Chunk中的公共部分的插件CommonsChunkPlugin。
項目中CommonsChunkPlugin的配置:
// 全部在 package.json 裏面依賴的包,都會被打包進 vendor.js 這個文件中。
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function(module, count) {
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
);
}
}),
// 抽取出代碼模塊的映射關係
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
chunks: ['vendor']
}),複製代碼
總結:
在現實項目中,項目上線後無疑就會要進行優化,特別是使用webpack打包後的項目,若是沒有進行優化,僅靠通常的腳手架搭建默認的配置,打包出來的項目性能堪憂,最直接體現的就是首屏加載速度,也是前端面試中常常考驗的哦,不慌,通過本文以上六種(包括但不限於)優化,打包從30分鐘,到2分鐘不到,總體還有優化空間,可使用其餘cdn
等再進行優化方式,快去試試吧!
------------------------------------------------------------------------------------------------