webpack性能優化
1.開發環境新能優化
1.1優化打包構建速度
1.1.1 HMR: hot module replacement / 熱模板替換
作用: 一個模板發生變化,只會重新打包這一個模塊(默認是打包所有)
1.2優化代碼調試
1.1.2 source-map
作用: 一種提供源代碼到構建後代碼映射技術 (如果 構建後代碼出錯了 可以通過映射追蹤源代碼錯誤)
2. 生產環境性能優化
2.1優化打包構建速度
2.1.1 開啓babel緩存
cacheDirectory: true,
讓第二次打包更快,綁定contenthash值讓線上運行緩存更好使
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
// 預設 指示babel做怎麼樣的兼容性處理
presets: [
['@babel/preset-env',
{
useBuiltIns: 'usage', // 按需加載
corejs: { version: 3 }, // 制定corejs的版本
targets: { // 指定具體的兼容性的版本
chrome: '60',
firefox: '60',
ie: '9',
safari: '10',
edge: '17',
},
},
],
],
// 開啓babel緩存
// 第二次構建時 會讀取之前的緩存
// 需要給 輸出文件帶上contnenthash值 不然無法更新變化
cacheDirectory: true,
},
},
- hash:每次webpack構建時會生成一個唯一的hash值,js和css同一個.
- chunkhash: 根據chunk生成的hash值,如果打包的來源於同一個chunk,那麼chuankhash值就是一樣的,js和css的還是一樣的
- contenthash: 根據文件內容生成的hash值.不同文件hash值不一樣
2.1.2 多進程打包 thread-loader
多用babel-loader 啓動時間大概爲600ms 只有工作消耗時間比較長的才需要多進程打包
一定要放在需要多進程的loader後面
{
/**
* 開啓多進程打包。
* 啓動時間大概爲600ms
* 只有工作消耗時間比較長的才需要多進程打包
*/
loader: 'thread-loader',
options: {
workers: 2, // 進程2個
},
}
2.1.3 externals
忽略文件,不進行打包
externals: {
//拒絕jq被打包進來
//線上的需要通過cdn引入這個包
jquery:'jQuery'
}
2.1.4 dll
使用dll技術,對某些庫(第三方庫:jq,react,vue…)進行單獨打包,只用打包一次,之後就不用打包了
注意:當運行webpack時,默認查找webpack.config.js配置文件
需要運行webpack.dll.js文件 要指定
–> webpack --config webpack.dll.js
<!--webpack.dll.js文件-->
const {resolve} = require('path')
const webpack = require('webpack')
module.export = {
entry: {
//最終打包生成的[name]--> jquery
//['jquery',xxx]-->要打包的庫
jquery:['jquery',xxx]
},
output: {
filename: '[name].js',
path: resolve(__dirname,'dll'),
//打包庫裏面向外面暴露出去的內容叫什麼名字
library:'[name]_[hash]'
},
plugins:[
new webpack.Dllplugin({
//映射庫暴露的內容名稱 name:'[name]_[hash]',
path: resolve(__dirname, 'dll/manifest.json')
})
],
mode: 'production'
}
<!--webpack.config.js文件-->
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const AddassetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin')
module.export = {
entry:'./src/index.js',
output: {
filename: 'built.js',
path: resolve(__dirname,'build'),
},
plugins:[
new HtmlWebpackPlugin({
template:'./src/index.html'
}),
//告訴webpack那些庫不參與打包,同時使用名稱時也得變
new webpack.DllReferencePlugin({
manifest: resolve(__dirname,'dll/manifest.json')
})
//將某個文件打包出去。並在html中自動引入資源
new AddassetHtmlWebpackPlugin({
filepath: resovle(__dirname,'dll/jquery.js')
})
],
mode: 'production'
}
2.2優化代碼運行性能
2.2.1 oneOf
module:{
rules:[
{
test: /\.js$/,
exclude: /'node_modules'/,
enforce: 'pre', // 優先執行
loader: 'eslint-loader',
options: {
// 自動修復
fix: true,
},
},
{
oneOf:[
{
exclude: /\.(css|js|html|less|jpg|png|gif)$/,
loader: 'file-loader',
options: {
outputPath: 'font',
},
},
]
}
]
}
不用oneOf的話 每個文件都要被所有Loader過濾一遍,注意:不能有兩個配置處理一中類型的文件
- 正常來說 一個文件只能被一個loader處理
- 當要被多個Loader處理的時候 需要弄清執行的順序 比如 先要 執行 eslint 在執行babel轉換 ,不然 先babel轉換成es5的話,再eslint回報錯
- 使用enforce:'pre’屬性,提到oneOf外面
2.2.2 tree shaking 去除無用代碼
注意: 1.必須使用es6模塊化 2.開啓production環境
作用: 減少代碼體積,會自動刪除沒有使用的代碼,使用production時會自動開啓,
防止css被刪除,需要在package.json中配置:
“sideEffects”:["*.css"]
2.2.3 code split代碼分割
分割成多個js文件,實現並行加載 速度更快
2.2.3.1 從入口入手
entry:{
//多個入口 多個bundle 多頁面
//單頁面 則單入口
main:'./src/js/index.js',
test:'./src/js/test.js',
},
output: {
//[name]文件名
fileName:'js/[name].[contenthash:10].js',
path: resolve(_dirname,'build')
}
2.2.3.1 optimization
// 可以將node_module中代碼單獨打包成一個chunk輸出(單入口)
//可以自動分析多入口chunk中,公共文件,有可以單獨打包成一個chunk,不會重複的打包多次(多入口)
optimization:{
splitChunks:{
chunks:'all'
}
}
//單入口 引入js打包成單獨的
// import動態導入
import(/* webpackChunkName:'test' */'./test')
.then(()=>{文件加載成功})
.catch(()=>{文件加載失敗})
2.2.3 懶加載
//js懶加載 需要使用時候才加載
document.getElementById('btn').onclick = function () {
import( /* webpackChunkName:'ppp' */ './ppp').then(({
add
}) => {
add(4, 6)
})
}
2.2.4預加載
//js預加載 webpackPrefetch 會在使用之前提前加載 等其他資源加載完畢 再偷偷加載
document.getElementById('btn').onclick = function () {
import( /* webpackChunkName: 'test',webpackPrefetch: true */ './ppp' ).then(({
add
}) => {
add(4, 6)
})
}
2.2.5 PWA 漸進式網絡開發應用程序
workbox --> workbox-webpack-plugin
<!--config.js-->
new WorkboxWebpackPlugin.GenerateSW({
// 幫助serverwork快速啓動 刪除舊的serverwork
// serverwork配置文件 一般在入口文件中配置
clientsClaim: true,
skipWaiting: true,
}),
<!--index.js-->
//註冊serverwork
//需要處理兼容性問題
//eslint不認識window等全局變量
// "env": {
// "browser": true //支持瀏覽器
// }
if ('serverWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serverWorker.register('/service-worker.js')
.then(() => {
console.log("serverworker註冊成功")
})
.catch(() => {
console.log("serverworker註冊失敗")
})
})
}
<!--package.json(eslint)-->
"eslintConfig": {
"extends": "airbnb-base",
"env": {
"browser": true
}
},