網上關於webpack的優化的已經很多了,只是都比較零散,結合實戰項目自己做個總結
webpack 優化,實際項目中主要做到了一下幾點:
1、 文件壓縮(css, js, html, 字體文件, 圖片文件)
2、 babel-loader 避免不必要的轉義
3、 babel-轉義結果進行緩存
4、 公共模塊的提取
5、 loader 轉爲多進程
6、 按需加載
7、 DllPlugin 增加開發時打包速度
8、 Gzip進行文件壓縮,webpack壓縮文件,後臺可以再次進行壓縮
接下來針對每一個細節點進行詳細說明
1、文件壓縮(html, css, js, 字體文件,圖片文件的壓縮和轉碼)
HtmlWebpackPlugin 官網鏈接 https://webpack.docschina.org/plugins/html-webpack-plugin/#src/components/Sidebar/Sidebar.jsx
關於 HtmlWebpackPlugin 的插件使用就不過多贅述,參考官方文檔,主要是用來壓縮代碼以及自動將打包後生成的就是文件插入到html中
如圖中所示的<script></script>標籤對js的引入都是該插件的功勞,具體用法和配置如下
plugins: [
new HtmlWebpackPlugin({
filename: config.build.index, // 指定項目的生成名稱
template: 'index.html', // 將模板指向根那個目錄
inject: true, // 指定生成的<script></script>放在那個目錄
// 去掉空格、註釋、多餘的應用等等都在這裏配置
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
chunksSortMode: 'dependency', // 成產環境下的第三方依賴進行壓縮
}),
]
js 壓縮用法同上,就不細講了參見官方文檔
https://webpack.docschina.org/guides/migrating/#uglifyjsplugin-sourcemap
css、圖片、字體文件壓縮主要通過 loader 來進行
配置如下:
const webpackConfig = {
module: {
rules: [
{
loader: 'css-loader',
options: {
sourceMap: options.sourceMap
}
}
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000, // 限制壓縮文件的大小
name: utils.assetsPath('media/[name].[hash:7].[ext]') // 文件的路徑
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
}
}
2、3 關於babel 的轉碼和轉碼緩存
const webpackConfig = {
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader?cacheDirectory=true', // 將轉譯結果緩存至文件系統
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')] // 針對特定的文件進行轉碼 通過include來配置,效率比 exclude 要高
},
]
}
}
4、公共模塊的提取配置文件如下
plugins配置如下
const webpackConfig = {
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks (module) {
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
]
}
主要是目的是將第三方依賴抽取到公共模塊放到vendor.js,然後針對動態引入的靜態文件做進一步的抽離放到 manifest.js 中
5、多進程轉碼
具體用法和配置如下:
const HappyPack = require('happypack') // 引入第三方依賴
const happyThreadPool = HappyPack.ThreadPool({size: 5}) // 設定五個線程池這裏默認設置5個進程
module.exports = {
plugins: [
new HappyPack({
id: 'happyBabel', // 定義唯一id
threadPool: happyThreadPool, // 指定進程池
loaders: ['babel-loader?cacheDirectory=true']
}),
],
module: {
rules: [
{
test: /\.js$/,
loader: 'happypack/loader?id=happyBabel', // 通過唯一id進行查找
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
},
]
}
}
6、按需加載配置如下,實際生產中減少渲染壓力
{
path: '/test',
name: 'test',
component: resolve => require(['@/test'], resolve)
}
7、DllPlugin 插件的使用(這裏提供簡單的配置,具體根據實際需要)
首先在你的build文件加下新建 webpack.dall.config.js 文件,內容如下
const path = require('path')
const webpack = require('webpack')
module.exports = {
entry: {
vendor: [
'aws-sdk',
'axios',
'moment',
'vue',
'vue-awesome-swiper',
'vue-router',
'vuex',
]
},
output: {
path: path.resolve(__dirname, '../static'), // 這裏通過絕對路徑指定生成文件
filename: '[name].dll.js',
library: '[name]_library'
},
plugins: [
new webpack.DllPlugin({
path: path.resolve(__dirname, '../static', '[name]-manifest.json'),
name: '[name]_library'
}),
]
}
控制檯輸入 webpack --config build/webpack.dall.config.js
或者 在package.json文件中進行如下配置 運行 npm/cnpm/yarn build build:dall
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"test": "cross-env NODE_ENV=test env_config=test node build/build.js",
"lint": "eslint --ext .js,.vue src",
"build": "cross-env NODE_ENV=production env_config=prod node build/build.js",
"build:dall": "webpack --config build/webpack.dall.config.js"
},
將會看到static目錄項生成 vendor.dall.js 和 vende-manifest.json文件,生成文件如下
接下來在生 build 下的 webpack.prod.conf.js 進行引用
到這個時候我們進行一口深呼吸,以爲打工打工告成,結果發現每次打包,然並卵,各位可憐的程序員,別急,萬里長征還剩最後一步,生成的js文件你不引用還能怪誰啊親
看清楚了怎麼引用
找到你的index.html文件手動引入 vendor.dll.js如下
第一次運行速度依然沒啥改變,當你再次運行的時候你會有飛一般的感覺
8、Gzip 文件壓縮 根據實際情況,具體配置如下
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin')
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
threshold: 10240,
minRatio: 0.8
})
)
}
以上是個人在實際生產項目中的webpack打包以及代碼壓縮的優化,從一開始的發版打包項目 接近一份到到 20幾秒將近一半時間的縮短,從一開始發版後端人員的抱怨:好沒好,你們打包這麼這麼慢 到 我靠!!!這麼快就好了。這是一種自我價值的體現和別人對你的肯定。
第一次寫博客,如有不妥之處歡迎大家批評指正,每一個優化點的原理就不再這裏細說了,先把效率搞上去,原理自行理解啊,個人對部分也不是特別清楚