持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第26天,点击查看活动详情
使用 CRA 脚手架创建的 React 项目,如果想要修改编译配置项,就需要通过npm run eject弹出配置后在官方原本的配置上进行魔改,同时 eject 操作是不可逆的,在配置弹出后,你后续将无法跟随官方的脚本去升级react-script版本。
这种魔改的方式对于不太熟悉webpack的人来说,也很难容易找到对应的配置参数。为了改变这个局面我便出现了以下几种修改配置的方式:
- 通过 CRA 官方支持的
--scripts-version参数,创建项目时使用自己重写过后的reat-scripts包。 - 使用 react-app-rewired + customize-cra 组合覆盖配置。
- 使用@craco/craco覆盖配置,该方式相较于第二种方式来说,配置更为简单。
配置步骤
-
安装
@craco/cracoyarn add @craco/craco -D -
修改
package.json中的scripts。{ "scripts": { "start": "craco start", "build": "craco build", "test": "craco test" } } -
项目根目录下创建
craco.config.js文件。/*craco.config.js */ module.export = { /* ...... */ }
@craco/craco有暴露出几个函数,分别在不同的环境下执行。when的话可以自己指定环境。需要三个参数,而其他的分别为两个,一个为执行的函数,另一个参数是在不满足条件时的值。
const { when, whenDev } = require("@craco/craco");
// 配置在开发环境需要用到的插件
const whenDevPlugin = whenDev(()=> {
return [new CircularDependencyPlugin()]
},[])
module.exports = {
eslint: {
mode: ESLINT_MODES.file,
configure: {
formatter: when(process.env.NODE_ENV === "CI", require("eslint-formatter-vso"))
}
},
webpack: {
plugins: [
new ConfigWebpackPlugin(),
...whenDevPlugin
]
}
};
接下来就是按照自己的需求,来对官方默认的webpack配置进行覆盖。
常用配置
修改打包输出目录
module.exports = {
webpack: {
configure:{
output: {
publicPath: '/',
path: path.resolve(__dirname, 'dist'), // 修改输出文件目录
}
},
}
}
路径别名
module.exports = {
// 路径别名配置
alias: {
'@': pathResolve('src'),
"@assets": pathResolve('src/assets'),
"@common": pathResolve('src/common'),
"@components": pathResolve('src/components'),
"@hooks": pathResolve('src/hooks'),
"@pages": pathResolve('src/pages'),
"@store": pathResolve('src/store'),
"@utils": pathResolve('src/utils')
},
}
显示编译进度
yarn add webpackbar -D
const WebpackBar = require("webpackbar"); // webpack 编译进度条
module.exports = {
webpack:{
plugins: {
add: [
new WebpackBar({
name: "webpack开始构建......",
color: "#2d56f8",
profile: true
})
]
}
}
}
循环依赖检查
yarn add circular-dependency-plugin -D
const { whenDev} = require("@craco/craco")
const CircularDependencyPlugin = require('circular-dependency-plugin')
const whenDevPlugin = whenDev(() => ([
// 循环依赖检查
new CircularDependencyPlugin({
exclude: /node_modules/,
include: /src/,
failOnError: true,
allowAsyncCycles: false,
cwd: process.cwd()
})
]), [])
显示打包模块报告
yarn add webpack-bundle-analyzer -D
const {whenDev, whenProd} = require("@craco/craco")
const {BundleAnalyzerPlugin} = require('webpack-bundle-analyzer')
// 开发环境用到的插件
const whenDevPlugin = whenDev(() => ([
new CircularDependencyPlugin({
exclude: /node_modules/,
include: /src/,
failOnError: true,
allowAsyncCycles: false,
cwd: process.cwd()
}),
new webpack.HotModuleReplacementPlugin()
]), [])
// 生产环境需要用到的插件
const whenProdPlugin = whenProd(() => ([
new BundleAnalyzerPlugin(),
]), [])
const isDev = process.env.NODE_ENV === "development"
module.exports = {
webpack: {
plugins: {
add: [
// webpack 构建进度条
new WebpackBar({
name: "webpack开始构建......",
color: "#2d56f8",
profile: true
}),
...isDev ? whenDevPlugin : whenProdPlugin
],
},
}
}
开启gizp压缩
项目打包后,一般体积还是比较大的,加载资源稍微有些慢,所以要对此优化。
首先 web 服务器和客户端必须支持gizp,即请求头的Accept-Language包含gzip,返回头的Conten-Encoding 也包含 gzip。
如果在服务端开启gizp压缩的话,如果文件比较大,还是比较耗费服务器资源的,整个过程也是比较久的,会导致用户体验不好。
另一种方案就是,在打包的时候生成gizp资源,服务端负责将生成的.gz文件返给客户端。
const CompressionWebpackPlugin = require("compression-webpack-plugin");
const whenProdPlugin = whenProd(() => ([
new BundleAnalyzerPlugin(),
new CompressionWebpackPlugin()
]), [])
UglifyJS Webpack Plugin
UglifyJS Webpack Plugin插件用来缩小(压缩优化)js文件。
module.exports = {
webpack: {
configure: {
optimization: {
minimizer: [new UglifyJsPlugin({
test: /.js(?.*)?$/i, // 测试匹配文件,
cache: false, // 是否启用文件缓存
parallel: true, // 使用多进程并行运行来提高构建速度
uglifyOptions: {
warning: false,
compress: {
drop_debugger: true, // 清除debugger
drop_console: false, // 是否清除所有console
pure_funcs: ["console.log", "console.info"], // 需要清除的console
},
},
})]
}
}
}
}