开发环境性能优化
一、优化打包构建速度
1、HMR 热模块替换
当一个模块发生变化时,只有打包一个模块,不会全打包。
开启方式:`devServer添加hot:true`
css文件:style-loader已包含不需要处理
html文件:开启hmr导致html文件不能热更新,需要再入口处更改:
`entry: ['./src/js/index.js', './src/index.html'],`
js文件:添加js代码,只能监听非入口js文件
if (module.hot) {
// 一旦为true,
module.hot.accept('./print.js', () => {
// 监听print.js的变化,一旦发生变化,默认不会重新打包构建
print();
});
}
二、优化代码调试
1、source-map一种提供源代码到构建后代码的映射技术
开发环境:速度快,调试更友好
速度快(eval>inline>cheap...)
eval-cheap-source-map>eval-source-map
调试更友好
source-map>cheap-module-source-map>cheap-source-map
--> eval-source-map折中的最好的选择 或者 eval-cheap-source-map
生产环境:源代码要不要隐藏,调试要不要更友好
内联会让代码体积变大,所以生产不用内联
nosource-source-map 全部隐藏
hidden-source-map 只隐藏源代码,会提示构建后代码错误
-->source-map / cheap-module-source-map
生产环境性能优化
一、优化打包构建速度
1、oneOf能让loader找到了就不再往下继续找了
oneOf:[
{
test: /\.css$/,
use: [...commonCssLoader]
},
{
test: /\.less$/,
use: [...commonCssLoader, 'less-loader']
},
]
2、babel缓存
与HMR相似,一个js文件改变后,只打包此文件,在babel-loader中开启
{
test: /\.js$/,
exclude: /node_modules/,
//
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env', // 基本兼容
{
// 按需加载
useBuiltIns: 'usage',
corejs: {
version: 3
},
// 指定兼容性做到哪个版本的浏览器
targets: {
chrome: '60',
firefox: '60',
ie: '9',
safari: '10',
edge: '17'
}
}
]
],
// 开启babel缓存,第二次构建时,会读取之前的缓存
cacheDirectory: true
}
},
二、优化代码运行的性能
1、文件资源缓存(hash-chunkhash-cotenthash)
在生产环境有强缓存时,若改变某文件重新打包,但是浏览器还会请求缓存的数据,导致看不到改变的内容。
三种hash值:
hash:每次webpack构建时会生成一个唯一的hash值
问题: 因为js和css同时使用一个hash值,如果重新打包,会导致所有缓存失效(可能我只是改了一个文件)
所以,使用chunkhash,根据chunk生成的hash值,如果打包来源同一个chunk,则hash值一样,又导致一个问题,js和css的hash值还是一样的,因为css是在js中被引入的,所以同属于一个chunk
所以,使用contenthash:根据文件的内容生成hash值
改动output文件配置:
output: {
filename: 'js/built.[contenthash:10].js',
path: resolve(__dirname, 'build')
},
改动css输出配置:
new MiniCssExtractPlugin({
filename: 'css/built.[contenthash:10].css'
}),
2、tree-shaking树摇
前提:使用es6模块化,使用production,作用,减少代码体积
package.json增加
`"sideEffects": ["*.css", "*.less"]`
3、code split代码分割
可以将一个文件分成多个文件并行加载速度更快,而且可以实现按需加载
1.第一种方式:多入口
entry: {
// 1.多入口
main: './src/js/index.js',
test: './src/js/test.js'
},
生成两个分别名叫main和test的js文件
output: {
// 1.[name]:取文件名
filename: 'js/[name].[contenthash:10].js',
path: resolve(__dirname, 'build')
},
2.第二种方式
// 2.可以将node_modules中代码单独打包一个chunk输出
// 比如js文件中引入了jquery,将juqery单独打包
// 也可以自动分析多入口chunk中,有没有公共文件(比如都引入了jquery),有的话将jquery只打包成一个chunk,不会生成两个
optimization: {
splitChunks: {
chunks: 'all'
}
},
3.第三种方式
单入口,但我想单独打包非入口文件的一个js文件
在入口js文件:
import(/* webpackChunkName: 'test' */'./test')
.then((add) => {
// 文件加载成功
// eslint-disable-next-line
console.log(add(2, 5));
})
.catch(() => {
// eslint-disable-next-line
console.log('文件加载失败')
})