目录
前言一、HMR 热更新1、什么是HMR2、HMR实现
二、source-map1、什么是source-map2、Source Map的配置项3、source-map实现
三、oneOf1、oneOf的作用2、oneOf使用
四、缓存1、babel 缓存2、文件资源缓存
五、小结
前言
大家都知道,webpack是现在主流的模块化打包工具,随着项目中打包出来的js体积越来越大,构建速度越来越慢,对其进行性能优化也是我们必做的事情。本篇文章会从各个性能方面进行讲解,希望对学习webpack的小伙伴们有所帮助。
一、HMR 热更新
1、什么是HMR
HMR 全称 Hot Module Replacement,翻译为模块热更新。当一个模块发生变化时,只会对该模块重新进行打包,而不会打包所有模块,这个特性对于开发环境来说非常重要,我们所需要做的就是更新我们的webpack-dev-server配置。
2、HMR实现
webpack5已经自动实现HRM热更新替换功能,所以我们在devServer中不需要添加任何代码,但html文件无法实现热更新,所以我们需要在主文件入口中将html文件引入
entry: ['./src/js/index.js', './src/index.html'],
另外新的模块替换老的模块后,业务层代码并不知道代码已经发生了变化,所以我们需要在业务层代码中添加处理模块更新函数,即在index.js中添加如下:
// index.js
if(module.hot) {
module.hot.accept('./other.js', function() {
hello()
})
}
判断HMR热模块替换已经开启的标识如下:
二、source-map
1、什么是source-map
sourcemap 本质上是一个信息文件,里面储存着打包前后代码的映射为位置关系及信息,可方便开发者快速定位错误。
2、Source Map的配置项
以上表格可能看不清,具体配置项详情可以参考官网:https://webpack.js.org/configuration/devtool/#root
3、source-map实现
devtool: 'eval-source-map'
在开发环境想要实现开发速度快,调试更友好,可采用eval-cheap–module-souce-map eval-source-map 在生产环境若需要隐藏代码,可采用nosources-source-map / hidden-source-map,若想速度快,可source-map / cheap-module-souce-map 注意:生产环境考虑到文件体积的原因,一般将映射文件生成到外部。 具体配置结合项目情况
三、oneOf
1、oneOf的作用
一般情况下,所有文件在执行的时候,都会将loader的rules过一遍,如果符合,就被相应的loader处理,不符合就直接过,这样非常浪费性能。oneOf是一个规则数组,当规则匹配时,只使用其中的第一个规则。
2、oneOf使用
若一个文件要被多个loader处理,那可以将将其放在oneOf外面
四、缓存
在这里会介绍两种缓存优化,即babel 缓存 和 文件资源缓存
1、babel 缓存
默认未设置缓存。当设置时,给定的目录将用于缓存加载器的结果。未来的webpack构建将尝试从缓存中读取,以避免在每次运行时都需要运行可能昂贵的Babel重新编译过程。cacheDirectory: true中将该值设置为true,加载器将使用node_modules/中的默认缓存目录。如果在任何根目录中都没有node_modules文件夹,则缓存/babel-loader或回退到默认的OS临时文件目录。
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: { version: 3 },
targets: {
chrome: '60',
firefox: '50'
}
}
]
],
// 开启babel缓存
// 第二次构建时,会读取之前的缓存
cacheDirectory: true
}
},
2、文件资源缓存
当请求的资源或者文件名称未出现变化时,浏览器会拿取缓存里面的资源,不会重新从服务器请求资源。
文件资源缓存有三种实现方案
hash:每次wepack构建时会生成一个唯一的hash值。可这会出现一个问题,即所有文件同时使用一个hash值,重新打包,所有文件的 hsah 值都改变,会导致所有缓存失效chunkhash:根据chunk生成的hash值。如果打包来源于同一个chunk,那么hash值就一样。产生的问题,由于css实在js中内引入的,所以它们的hash值还是一样的contenthash: 根据文件的内容生成hash值。不同文件hash值一定不一样。最优方案。
简单创建一个node服务器:
const express = require('express');
const app = express();
//需要将dist文件作为静态资源缓存
app.use(express.static('dist', { maxAge: 2000 * 3600 }));
app.listen(9000);
启动服务器后在需要缓存的文件后面加上contenthash即可
实现效果
五、小结
最终整体代码:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin'); //通过 npm 安装
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
// 设置nodejs环境变量
process.env.NODE_ENV = 'development';
const config = {
entry:'./src/js/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'js/dist[contenthash:10].js'
},
module: {
rules: [
{
oneOf: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
[
"postcss-preset-env",
{}
],
],
},
}
}
],
},
{
//打包图片资源 处理 css 文件的 img背景 图片
test:/\.(jpg|png|gif)$/,
type: 'asset/resource',
generator:{
filename:'img/[hash:10][ext]',
},
},
{
// 处理 html 文件的 img 图片
test:/\.html$/,
loader:'html-loader',
},
{
//打包图标字体资源
test: /\.(ttf|eof|woff2)$/,
type: 'asset/resource',
generator:{
filename:'font/[hash:10][ext]',
},
},
{
//打包图标字体资源
exclude: /\.(ttf|eof|woff2|css|html|js|png|gif|jpg)$/,
type: 'asset/resource',
generator:{
filename:'other/[hash:10][ext]',
}
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
// 按需加载
useBuiltIns: 'usage',
// 指定core-js版本
corejs: {
version: 3
},
// 指定兼容性做到哪个版本浏览器
targets: {
chrome: '60',
firefox: '60',
ie: '9',
safari: '10',
edge: '17'
}
}
]
],
// 开启babel缓存
// 第二次构建时,会读取之前的缓存
cacheDirectory: true
}
}
}
]
}
]
},
plugins:[
new HtmlWebpackPlugin({
template : './src/index.html',
// 压缩html代码
minify: {
// 移除空格
collapseWhitespace: true,
// 移除注释
removeComments: true
}
}),
// 使用单独生成css文件的插件,打包时会将css文件独立出去
new MiniCssExtractPlugin({
// 指定文件的输出路径和文件名
filename: 'css/index[contenthash:10].css'
}),
],
optimization: {
//这将使CSS优化只在生产模式。
// 如果你想在开发中运行它,设置优化。最小化选项为true:
minimizer: [
new CssMinimizerPlugin(),
],
minimize: true,
},
mode:'development',
devServer: {
//热加载 npx webpack server
static: {
directory: path.join(__dirname, 'build'),
},
compress: true,
port: 9000,
open: true,
/* hot: true*/
},
};
module.exports = config;
各位小伙伴们,由于webpack性能优化考虑的地方较多,所以先介绍到这里,后面会更新webpack性能二。创作不易,若你觉得对你有所帮助的话麻烦点赞关注一下哟。若有什么不足的地方,也麻烦各位大佬指点出来。
文章链接
发表评论