- 提升熱更新速度:
- 提升熱更新速度,上百頁 2000ms內搞定,10幾頁面區別不大
//在.env.development環境變量配置
VUE_CLI_BABEL_TRANSPILE_MODULES:true
- 原理:利用插件,在開發環境中將異步組件變爲同步引入,也就是import()轉化爲require())
- 通常頁面到達幾十上百,熱更新慢的狀況下須要用到。
- webpack5 即將發佈,大幅提升了打包和編譯速度
- 分析打包時長:
- webpack-bundle-analyzer 分析打包後的模塊文件大小
npm run build -- --report
npm install --save-dev speed-measure-webpack-plugin
//vue.config.js
//導入速度分析插件
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
//實例化插件
const smp = new SpeedMeasurePlugin();
module.exports = {
configureWebpack: smp.wrap({
plugins: [
// 這裏是本身項目裏須要使用到的其餘插件
new yourOtherPlugin()
]
})
}
- 較耗時:代碼的編譯或壓縮(轉化 AST樹 -> 遍歷AST樹 -> 轉回JS代碼)
- 編譯 JS、CSS 的 Loader
- 壓縮 JS、CSS 的 Plugin
- 緩存:讓二次構建時,不須要再去作重複的工做[沒有變化的直接使用緩存,速度更快]
- 開啓Loader、壓縮插件的cache配置【如babel-loader的cacheDirectory:true】,uglifyjs-webpack-plugin【如cache: true】,構建完將緩存存放在node_modules/.cache/..。
- cache-loader:將 loader 的編譯結果寫入硬盤緩存,再次構建若是文件沒有發生變化則會直接拉取緩存,添加在時間長的 loader 的最前面。
module: {
rules: [
{
test: /\.ext$/,
use: ['cache-loader', ...loaders],
include: path.resolve('src'),
},
],
},
- 多核:充分利用了硬件自己的優點
- happypack:開啓系統CPU最大線程,經過插件將loader包裝,暴露id,直接module.rules引用該id。
//安裝:npm install happypack -D
//引入:const Happypack = require('happypack');
exports.plugins = [
new Happypack({
id: 'jsx',
threads: 4,
loaders: [ 'babel-loader' ]
}),
new Happypack({
id: 'styles',
threads: 2,
loaders: [ 'style-loader', 'css-loader', 'less-loader' ]
})
];
exports.module.rules = [
{
test: /\.js$/,
use: 'Happypack/loader?id=jsx'
},
{
test: /\.less$/,
use: 'Happypack/loader?id=styles'
},
]
- thread-loader:添加在此loader後面的放入單獨的 worker 池裏運行,配置簡單
//安裝:npm install thread-loader -D
module.exports = {
module: {
//個人項目中,babel-loader耗時比較長,因此我給它配置 thread-loader
rules: [
{
test: /\.jsx?$/,
use: ['thread-loader', 'cache-loader', 'babel-loader']
}
]
}
}
- 默認的TerserWebpackPlugin:開啓了多進程和緩存,緩存文件 node_modules/.cache/terser-webpack-plugin
- 其餘並行壓縮插件:
- webpack-parallel-uglify-plugin:子進程併發執行把結果送回主進程,多核並行壓縮來提高壓縮速度
- uglifyjs-webpack-plugin自帶的parallel:【如parallel: true】配置項開啓多核編譯
- 抽離:Vue全家桶、echarts、element-ui、工具庫lodash不常變動的依賴 【幾十秒】
- 內置webpack的 DllPlugin 和 DllReferencePlugin 引入dll, 經過DllPlugin來對那些咱們引用可是絕對不會修改的npm包來進行預編譯,再經過DllReferencePlugin將預編譯的模塊加載進來,避免反覆編譯浪費時間。新建一個webpack.dll.config.js 的配置文件,通常不變化,若是變了,新的dll文件名便會加上新的hash
// webpack.config.dll.js
const webpack = require('webpack');
const path = require('path');
module.exports = {
entry: {
react: ['react', 'react-dom']
},
mode: 'production',
output: {
filename: '[name].dll.[hash:6].js',
path: path.resolve(__dirname, 'dist', 'dll'),
library: '[name]_dll' //暴露給外部使用
//libraryTarget 指定如何暴露內容,缺省時就是 var
},
plugins: [
new webpack.DllPlugin({
//name和library一致
name: '[name]_dll',
path: path.resolve(__dirname, 'dist', 'dll', 'manifest.json') //manifest.json的生成路徑
})
]
}
// package.json 中新增 dll 命令
{
"scripts": {
"build:dll": "webpack --config webpack.config.dll.js"
},
}
// npm run build:dll 後,會生成
dist
└── dll
├── manifest.json
└── react.dll.9dcd9d.js
// manifest.json 用於讓 DLLReferencePlugin 映射到相關依賴上。至此 dll 準備工做完成,接下來在 webpack 中引用便可。
// webpack.config.js
const webpack = require('webpack');
const path = require('path');
module.exports = {
//...
devServer: {
contentBase: path.resolve(__dirname, 'dist')
},
plugins: [
new webpack.DllReferencePlugin({
manifest: path.resolve(__dirname, 'dist', 'dll', 'manifest.json')
}),
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: ['**/*', '!dll', '!dll/**'] //不刪除dll目錄
}),
//...
]
}
// 使用 npm run build 構建,能夠看到 bundle.js 的體積大大減小。
// 修改 public/index.html 文件,在其中引入 react.dll.js
<script src="/dll/react.dll.9dcd9d.js"></script>
- 配置Externals(推薦):外部引入,將不須要打包的靜態資源從構建邏輯中剔除,使用 CDN 的方式去引用。
- 步驟:在externals中配置key[包名]+value[CDN全局變量名],而後在HTML中引入CDN的script 標籤。就能實現import引入了。
//webpack.config.js
module.exports = {
//...
externals: {
//jquery經過script引入以後,全局中即有了 jQuery 變量
'jquery': 'jQuery'
}
}
<script src="https://cdn.bootcss.com/react/16.9.0/umd/react.production.min.js"></script>
- 有些 CDN 服務不穩定,儘可能選擇成熟的CDN服務。