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
}
},