修改CRA项目的配置
使用create-react-app 创建的项目默认是无法修改其内部的webpack配置的,不像vue-cli那样可以通过一个配置文件修改。 虽然有一个eject 命令可以是将配置完全暴露出来,但这是一个不可逆的操作,同时也会失去CRA带来的便利和后续升级。
如果想要无 eject 重写 CRA 配置,目前成熟的是下面这几种方式
通过 CRA 官方支持的 --scripts-version 参数,创建项目时使用自己重写过的 react-scripts 包
使用 react-app-rewired + customize-cra 组合覆盖配置
使用 craco 覆盖配置
这里我选择的是craco
安装
安装依赖
yarn add @craco/craco
复制代码
修改pacage.json中的命令
{
"scripts":{
"start": "craco start",
"build": "craco build",
"test": "craco test"
}
}
复制代码
在根目录创建craco.config.js配置文件
/* craco.config.js */
module.exports = {
// ...
webpack: {},
babel: {},
}
复制代码
基础的配置到此完成了,接下来是处理各种配置的覆盖,完整的 craco.config.js 配置文件结构,可以在 craco 官方的文档中详细查询:Configuration File 。
注意! 目前的craco最新版本v6.4.3仅支持cra4创建的项目
构建体积分析
首先引入了webpack-bundle-analyzer 这个插件来分析一下构建产物的组成
/* craco.config.js */
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
module.exports = {
webpack: {
plugins: [
new BundleAnalyzerPlugin({
analyzerMode: 'server',
analyzerHost: '127.0.0.1',
analyzerPort: 8888,
openAnalyzer: true, // 构建完打开浏览器
reportFilename: path.resolve(__dirname, `analyzer/index.html`),
}),
],
}
}
复制代码
在使用yarn build命令打包后,就可以得到一个分析图,包含了每个chunk的组成部分。
可以看到这里项目的包体积高达24M,有非常多的重复文件被打包。
代码拆分,减少重复打包
由于使用了懒加载,每个页面都对应一个独立的chunk文件。有些使用比较频繁的库,会被重复打包进每个chunk中,增加了很多体积。这里使用 SplitChunksPlugin来将这些库拆成一个单独的chunk。
在craco中可以通过configure属性拿到webpack的配置对象,对其进行修改来配置,将重复的包拆分出去。
经过对图的分析,发现jsoneditor,echarts,antv等库对包体积的影响比较大,所以将他们拆分出去。 除了将重复打包的内容拆分之外,我们还可以将项目的基本框架也提取到一个单独的文件 base.js 中,该文件包含了所有网页的基础运行环境。(为了长期缓存 base.js 文件)
webpack: {
plugins: [/** */],
configure: (webpackConfig, { env: webpackEnv, paths }) => {
webpackConfig.optimization.splitChunks = {
...webpackConfig.optimization.splitChunks,
cacheGroups: {
base: {
// 基本框架
chunks: 'all',
test: /(react|react-dom|react-dom-router)/,
name: 'base',
priority: 100,
},
jsoneditor: {
test: /jsoneditor/,
name: 'jsoneditor',
priority: 100,
},
echarts: {
test: /(echarts)/,
name: 'echarts',
priority: 100,
},
g2: {
test: /@antv/,
name: 'g2',
priority: 100,
},
commons: {
chunks: 'all',
// 将两个以上的chunk所共享的模块打包至commons组。
minChunks: 2,
name: 'commons',
priority: 80,
},
},
};
return webpackConfig;
},
}
复制代码
将它拆分出去后,包体积直接减少到了7.61M,提升显著。
按需加载大体积的库
从优化后的分析图中我发现了一个体积很大的库BizCharts,而项目中这个库实际上只使用过不多的几个组件.
这种情况下,可以通过修改引入方式来进行按需引入。
import { Chart, Axis, Legend, Tooltip } from 'bizcharts';
// 改为手动按需引入
import Chart from 'bizcharts/lib/components/Chart'
import Axis from 'bizcharts/lib/components/Axis'
import ......
复制代码
手动修改所有的引入非常的麻烦,这时可以通过babel插件来帮我们在构建时修改。
babel-plugin-import这个插件原本是用来给antd按需引入的,但在这里我们也能用于其他的库
babel: {
plugins: [
[
'import',
{ libraryName: 'bizcharts', libraryDirectory: 'lib/components' },
],
],
}
复制代码
构建速度优化
HardSourceWebpackPlugin 插件可以为模块提供中间缓存。首次构建时间没有太大变化,但是第二次开始,构建时间大约可以节约 80%。
在我的项目中,一开始的构建的速度为26s,配置完插件生成缓存后为15s,节约了60%多的时间。
附上配置
// craco.config.js
const path = require('path');
const CracoLessPlugin = require('craco-less');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const WebpackBar = require('webpackbar');
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
const env = process.env.REACT_APP_ENV;
module.exports = {
webpack: {
plugins: [
new BundleAnalyzerPlugin({
analyzerMode: env !== 'development' ? 'server' : 'disabled',
analyzerHost: '127.0.0.1',
analyzerPort: 8888,
openAnalyzer: true,
reportFilename: path.resolve(__dirname, `analyzer/index.html`),
}),
new WebpackBar({
profile: true,
color: '#fa8c16',
}),
new HardSourceWebpackPlugin(),
],
alias: {
layouts: path.resolve(__dirname, './src/app/layouts'),
containers: path.resolve(__dirname, './src/app/containers'),
components: path.resolve(__dirname, './src/app/components'),
utils: path.resolve(__dirname, './src/utils'),
routers: path.resolve(__dirname, './src/routers'),
},
configure: (webpackConfig, { env: webpackEnv, paths }) => {
webpackConfig.externals = {
'ckeditor5-custom-build': 'ClassicEditor',
};
webpackConfig.optimization.splitChunks = {
...webpackConfig.optimization.splitChunks,
cacheGroups: {
base: {
// 基本框架
chunks: 'all',
test: /(react|react-dom|react-dom-router)/,
name: 'base',
priority: 100,
},
jsoneditor: {
test: /jsoneditor/,
name: 'jsoneditor',
priority: 100,
},
echarts: {
test: /(echarts)/,
name: 'echarts',
priority: 100,
},
g2: {
test: /@antv/,
name: 'g2',
priority: 100,
},
commons: {
chunks: 'all',
// 将两个以上的chunk所共享的模块打包至commons组。
minChunks: 2,
name: 'commons',
priority: 80,
},
},
};
return webpackConfig;
},
},
babel: {
plugins: [
[ // antd 的按需加载用和自动引入样式文件
'import',
{
libraryName: 'antd',
libraryDirectory: 'es',
style: true,
},
],
// bizcharts的按需加载
['import', { libraryName: 'bizcharts', libraryDirectory: 'lib/components' }, 'biz'],
],
},
plugins: [
{ // 修改antd主题
plugin: CracoLessPlugin,
options: {
lessLoaderOptions: {
lessOptions: {
math: 'always',
modifyVars: {
'@primary-color': '#1890ff', //主题颜色
},
javascriptEnabled: true,
},
},
},
},
],
};
复制代码
总结
这次的优化主要是针对减小构建产物体积的,体积从24M -> 6.8M左右,提升还是非常大的。
通过了代码分割的方式减少库被重复打包,以及按需加载一些很大的库,同时通过一些缓存的插件提升了构建速度。
最后
如果你觉得此文对你有一丁点帮助,点个赞。或者可以加入我的开发交流群:1025263163相互学习,我们会有专业的技术答疑解惑
如果你觉得这篇文章对你有点用的话,麻烦请给我们的开源项目点点star:http://github.crmeb.net/u/defu不胜感激 !
PHP学习手册:https://doc.crmeb.com
技术交流论坛:https://q.crmeb.com
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。