webpack5搭建react框架-配置优化
一、前言
使用webpack5已经搭建好了基础的开发环境和生产环境,但是有些功能在使用的时候还可以进一步优化,所以今天就来将之前的配置做一下最终的优化。
二、配置优化
1、设置扩展名和别名
目前的配置中我们在引入一个自定义的文件或者组件时必须使用完整的名称才可以,否则就会报错,那么我们可以在配置中增加一些高频使用的文件扩展名,这样就不用我们每次都手动把文件名写全,让webpack自动去解析。
修改webpack.base.js 文件增加jsx,js文件扩展名配置
// webpack.base.js
module.exports = {
resolve: {
// 扩展名
extensions: ['.jsx', '.js'],
},
}
重新启动项目后删除app.jsx页面中test组件.jsx后缀,项目正常加载。
// app.jsx
import Test from './components/test';
export default function app() {
return (
<div className="app-wrap">
<Test />
</div>
);
}
项目中我们还可以给目录设置别名以简化模块的引用
修改webpack.base.js 文件增加资源目录别名配置
// webpack.base.js
const { resolve } = require('./tools');
module.exports = {
resolve: {
// 设置别名
alias: {
'@asset': resolve('src/assets')
}
},
}
然后将app.jsx目录下的内容修改为我们设置的别名@asset,执行npm run dev指令后查看项目加载效果
import wImage from '@asset/images/wind.png';
import gImage from '@asset/images/girl.jpeg';
export default function app() {
return (
<div className="app-wrap">
<img src={wImage} alt="" />
<img src={gImage} alt="" />
</div>
);
}
2、增加css样式浏览器前缀
css样式在大多数浏览器中的兼容性已经很好了,但是在某些低版本中可能需要增加浏览器前缀进行兼容,所以我们就使用插件在构建的时候自动的为我们的新样式属性增加浏览器前缀。
安装
npm install postcss-loader postcss-preset-env --save-dev
修改webpack.base.js文件配置使用postcss-loader(在css-loader后使用)
// webpack.base.js
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
// 生产环境下使用MiniCssExtractPlugin.loader
isProd() ? MiniCssExtractPlugin.loader : 'style-loader',
'css-loader',
'postcss-loader'
]
},
// 当使用多个loader处理模块时,use为数组格式,并且loader的执行顺序为从下到上,从后往前。
{
test: /\.less$/,
use: [
isProd() ? MiniCssExtractPlugin.loader : 'style-loader',
'css-loader',
'postcss-loader',
'less-loader'
],
include: resolve("src"),
},
]
},
}
使用postcss-loader 进行css样式转义时和babel-loader一样也需要使用插件,并且创建postcss.config.js 配置文件(和babel.config.js同级)
注意: 如果是只进行浏览器前缀的添加也可以使用autoprefixer配置更简单,postcss-preset-env不光可以自动添加浏览器前缀还可以进行一些其他高级配置。
创建postcss.config.js 并增加 postcss-loader配置
// postcss.config.js
module.exports = {
plugins: [
require('postcss-preset-env')({
// // options
})
]
}
// postcss-preset-env的配置项
/*
plugins: [
require('postcss-preset-env')({
stage: 0, // 设置转换的阶段,默认为 2
autoprefixer: { grid: true }, // 自动添加浏览器前缀,这里设置是否添加 grid 前缀
features: {
'nesting-rules': true, // 启用嵌套规则
'custom-properties': true, // 启用 CSS 变量
'color-mod-function': true // 启用 color-mod() 函数
}
})
]
stage 参数的取值:
0 - 预览版,包含所有尚未标准化的特性
1 - 候选版,包含已经被标准化的特性和被广泛使用的特性
2 - 正式版,包含已经被标准化的特性和被广泛使用的特性,但不包含尚未实现或已经弃用的特性
3 - 已弃用版,包含已经废弃的特性
features 参数的取值:
autoprefixer - 自动添加浏览器前缀
custom-media-queries - 启用自定义媒体查询
custom-properties - 启用 CSS 变量
custom-selectors - 启用自定义选择器
color-mod-function - 启用 color-mod() 函数
media-query-ranges - 启用媒体查询范围
nesting-rules - 启用嵌套规则
not-pseudo-class - 启用 :not 伪类
overflow-property - 启用 overflow-block 和 overflow-inline 属性
place-properties - 启用 place-* 属性
system-ui-font-family - 启用 system-ui 字体
*/
创建需要兼容到那些浏览器的配置文件.browserslistrc (和postcss.config.js 同级, 同时也对babel-loader生效)
修改.browserslistrc 文件
IE 6 # 兼容IE 6
chrome 35 # 兼容chrome 35
> 0.5% # 超过0.5%份额
下面执行在test组件样式文件中增加transform: translateX(10%) 属性,执行npm run dev 查看前缀添加效果
3、代码分割
在我们项目中不但有自己的业务代码还有第三方的依赖库,把他们都打包成一个文件时,那么在加载资源时可能会造成阻塞,所以可以将第三方的依赖单独拆分出来自己业务中一些重复使用的模块也可以拆分出来进行单独加载。webpack5就提供了进行代码拆分的配置
修改webpack.prod.js文件增加代码分割配置
// webpack.prod.js
module.exports = merge(baseConfig, {
optimization: {
splitChunks: { // 分割代码
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/, // 匹配node_modules代码
name: 'vendors', // 提取文件名, 也可以使用filename来详细设置
minChunks: 1, // 使用一次就提取出来
chunks: 'all', // 可以设置只提取初始化initial, 异步的async, 全部 all
minSize: 1, // 代码体积大于1就提取出来
priority: -10, // 提取优先级,数越大优先级越高
},
common: { // 提取项目公共代码
test: /[\\/]src[\\/]/,
name: 'common',
chunks: 'all',
minChunks: 2,
minSize: 20000,
priority: -20,
reuseExistingChunk: true, // 如果当前模块已经被打包过了,则直接使用已有的模块,不再重新打包
},
}
},
},
})
执行npm run build打包命令,查看dist目录下的打包资源,并启动live-server查看页面加载效果
4、代码映射配置
在页面加载过程中有时候会出现代码错误,点开错误的时候都是编译后的代码非常不利于定位和调式,所以我们在开发环境时就需要增加代码映射当出现错误的时候可以直接映射到我们源码的地方,注意生产环境上不需要开启代码映射功能。
修改webpack.dev.js 文件增加代码映射配置
// webpack.dev.js
module.exports = merge(baseConfig, {
devtool: 'eval-cheap-module-source-map', // 代码映射
})
devtool有很多的选项,一般开发环境中推荐选择eval-cheap-module-source-map模式,更多模式可以查看https://www.webpackjs.com/configuration/devtool/#root, 然后再自定义组件test中增加错误信息,对比查看代码映射前后错误信息定位对比效果
5、多进程配置
在webpack中loader执行是在单进程中执行的所以在遇到一些比较耗时的loader时,我们可以将他们放在单独开辟的进程池中,进行多进程解析大大提升解析速度。
安装
npm install --save-dev thread-loader
修改webpack.base.js文件增加多进程打包配置
// webpack.base.js
module.exports = {
module: {
rules: [
{
test: /\.js[x]?$/, // 设置所匹配要解析的文件
use: [
{
loader: 'thread-loader', // 开启多进程打包
options: {
worker: 3,
}
},
'babel-loader'
],
include: resolve('src')
},
]
},
}
将thread-loader 放置在其他 loader 之前。放置在此 loader 之后的 loader 会在一个独立的 worker 池中运行。
注意: 只有在处理较大的项目和模块是才使用thread-loader,因为开启一个进程需要额外的耗时 600ms 左右,另外开启的进程数量不能超过CPU核心数,否则会导致线程竞争反而降低性能( 可以使用os.cpus().length获取CPU核心数 )。
6、打包耗时分析
在对项目进行打包时,如果感觉项目打包时间还是比较慢,那我们可以增加打包耗时分析,看看哪里耗时比较大然后针对耗时较大的插件或者loader进行单独优化。
安装插件
npm install --save-dev speed-measure-webpack-plugin
使用speed-measure-webpack-plugin时会造成额外的开销,所以我们创建单独的文件来进行配置,不对生产环境进行影响。
创建webpack.analyzer.js文件(和webpack.prod.js同级)
// webpack.analyzer.js
const { merge } = require('webpack-merge');
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin'); // 引入构建分析插件
const smp = new SpeedMeasurePlugin(); // 实例化插件
const prodConfig = require('./webpack.prod');
module.exports = smp.wrap(merge(prodConfig, {
// 可以传构建相关的配置
}));
修改package.json文件增加分析指令
"scripts": {
"analyzer": "cross-env NODE_ENV=production webpack --config config/webpack.analyzer.js"
},
执行npm run analyzer指令查看打包耗时结果(有些 Loader 或者 Plugin 新版本不兼容可能会报错,可版本降级处理),也可以直接查看
7、打包文件大小分析
上面对打包过程中每一步的耗时进行分析,我们还可以对打包后的文件大小进行分析。
安装插件
npm install --save-dev webpack-bundle-analyzer
修改webpack.analyzer.js 文件
// webpack.analyzer.js
const { merge } = require('webpack-merge');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const prodConfig = require('./webpack.prod');
module.exports = merge(prodConfig, {
// 可以传构建相关的配置
plugins: [
new BundleAnalyzerPlugin({
analyzerPort: 8899, // 端口号
})
]
})
// webpack-bundle-analyzer 配置属性
// analyzerMode: 'server', // 分析模式:server-在浏览器中打开,static-生成静态报告
// analyzerHost: '127.0.0.1', // 打开的主机名,默认为localhost
// analyzerPort: '8888', // 端口号,默认为8888
// reportFilename: 'report.html', // 生成的报告文件名,默认为report.html
// defaultSizes: 'parsed', // 默认显示的文件大小:parsed-解析后的大小,gzip-压缩后的大小,stat-文件大小
// openAnalyzer: true, // 是否自动在浏览器中打开报告
// generateStatsFile: false, // 是否生成stats.json文件
// statsFilename: 'stats.json', // stats.json文件的名称和路径,默认为webpack官方提供的默认值
// logLevel: 'info' // 日志级别:info,warn,error,silent
执行npm run analyzer查看分析结果,它会自动打开一个新的页面展示分析结果(它可以和耗时分析插件配合使用,也可以单独使用)
三、结语
关于webpack5配置的优化就先到这里,其实关于他的优化还有许多,比如自带的tree-shaking、懒加载等等,可以根据项目的实际情况和业务场景直接使用即可不要安装额外的插件。