引言
其實,相信很多隻是從事快速應用開發的同學,對於 Webpack
打包優化方面可能是一知半解(我深有感觸…)。但是,作爲一名從事編程的人,我一直推崇的就是用編程高效、快速解決一些問題。因爲,如果只是解決問題,我想這不是我想要的,就比如只會迭代不會遞歸,以及還停留在 console.log
調試代碼等等。
當然,人總是從未知向知一點到知一些到構建完整的知識體系過渡,只要堅持,未知終將變爲已知。那麼,回到今天的正題,如何用Webpack
進行一些打包的優化?
在我們開始本篇文章之前,我們需要先安裝兩個 Plugin
用於分析 Wepack
打包的時間和打包後的各個模塊的大小:
1.speed-measure-webpack-plugin
,它會分析每個 Loader
在打包過程中的耗時:
a. 首先安裝依賴
npm install --save-dev speed-measure-webpack-plugin
b. 在 webpack.config.js
中使用
// 引入
const SpeedMeasurePlugin = require('speed-measure-plugin')
const speedMeasure = new SpeedMeasurePlugin
// 配置
const config = {
....
}
// 用 speed 插件包裹導出
module.exports = speedMeasure.wrap(config)
2.webpack-bundle-analyzer
,它會分析打包後的各個模塊所佔用的大小:
a. 安裝依賴
npm install --save-dev webpack-bundle-analyzer
b. 配置 webpack.config.js
// 引入
const BundleAnalyzer = require('webpack-bundle-analyzer')
const config = {
...
plugin: [
...
new BundleAnalyzer()
]
}
c. 配置 package.js
中的 scripts
命令
{
...
'scripts`: {
"analyze": "cross-env NODE_ENV=production npm_config_report=true npm run build",
}
}
一、resolve 優化
resolve.modules
配置第三方模塊對應的路徑,即針對於代碼中import from 'react'
之類的對應 from
後面的字符串,即不是絕對路徑,又不是相對路徑時命中的邏輯。
resolve: {
modules: [
resolve('node_modules') // 指定第三方模塊去 node_modules 中查找
]
}
resolve.alias
針對特定的路徑匹配(可以理解爲指定)到對應已設好的目錄,通常我們會用來指定自定義的組件文件夾。
resolve: {
alias: [
'component': resolve('src/component')
]
}
二、module 優化
noParse
忽略掉對一些文件的解析,例如 Jquery
之類的。
module: {
noParse: /Jquery/
}
loader優化
主要是用好一些 queryparams
以及精確地指定需要使用和不使用 loader
的地方,即 include
和 exclude
,例如對於 babel-loader
而言:
modulde: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader?cacheDirectory=true', // 緩存解析過的文件
include: resolve('src'),
exclude: /node_modules/
}
]
}
三、plugins 優化
webpack-parallel-uglify-plugin
主要是針對於代碼壓縮方面的優化,當然這是相對於Webpack.optimize.UglifyJsPlugin
而言,因爲 Webpack
自帶的 UglifyJsPlugin
只能同步壓縮代碼,而webpack-parallel-uglify-plugin
可以實現並行壓縮代碼的效果,這樣一來就很好地利用了 CPU
,從而提高壓縮速度。
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin')
new ParallelUglifyPlugin({
parallel: true, // 開啓並行壓縮 默認線程=cup-1
cache: path.resolve(__dirname, 'dist'),
uglifyOptions: {
output: {
comments: false
},
compress: {
drop_debugger: true,
drop_console: true
},
warnings: false
}
}),
hard-source-webpack-plugin
爲模塊提供中間緩存的作用,即在很大程度上會縮短第二次打包的時間。
const HardSourcePlugin = require('hard-source-webpack-plugin')
plugins: [
new HardSourcePlugin
]
happypack
在Webpack
壓縮的過程中,很重要的一個過程就是babel
解析轉化代碼的過程,所以優化這個過程,在一定程度上也可以提高我們的打包速度。同樣地,由於Webpack
整個打包地過程是同步進行的,而happypack
則可以實現多線程並行打包,它通常用於配合loader
一起使用,例如它和babel-loader
一起使用:
const HappyPack = require('happypack')
const os = require('os')
const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length })
module: {
rules: [
{
test: /\.js$/,
loader: isProd ? 'happypack/loader?id=happybabel':'babel-loader' // 需要區分生產和開發環境
include: [resolve('src')],
exclude: /node_modules/,
}
]
},
plugins: isProd ? [
new HappyPack({
id: 'happyBabel',
loaders: [{
loader: 'babel-loader?cacheDirectory=true'
}],
threadPool: happyThreadPool,
verbose: true // 允許 HappyPack 輸出日誌
})
]:[]
四、其他優化
externals
對於一些文件我們可以預先放在 CDN
上,然後 index.html
中通過 script
標籤引入,通過配置 externals
,我們仍然可以在代碼中通過 import
導入。例如,拿 Jquery
舉例:
在 index.html
中引入:
<script src="http://wjc.cdn.com/jquery.min.js"></script>
在 webpack
中配置 externals
:
{
externals: {
'jquery': 'jquery'
}
}
在項目中使用:
import $ from 'jquery'
總結
其實對於 webpack
的優化還有其他的途徑,例如將第三方依賴分離出來直接放到 CDN
上,當然首先要保證這些依賴已經編譯成 ES5
。又或者結合 DllPlugin
將第三方依賴(例如 Vue)之類的不會發生變化的單獨打包成js
文件,然後在index.html
中通過script
標籤引入等等。後續,時間充裕我會繼續補上各種優化手段。