Modify the configuration of CRA project
A project created with create react app cannot modify its internal webpack configuration by default. Unlike Vue cli, it can be modified through a configuration file. Although an eject command can completely expose the configuration, it is an irreversible operation and will lose the convenience brought by CRA and subsequent upgrades.
If you want to rewrite CRA configuration without eject, the following methods are mature at present
Through the -- scripts version parameter officially supported by CRA, you can use your own rewritten react scripts package when creating a project
Use react app rewired + customize CRA combination to override configuration
Override configuration with craco
I choose craco here
install
Installation dependency
yarn add @craco/craco Copy code
Modify pacage Commands in JSON
{ "scripts":{ "start": "craco start", "build": "craco build", "test": "craco test" } } Copy code
Create craco.com in the root directory config. JS configuration file
/* craco.config.js */ module.exports = { // ... webpack: {}, babel: {}, } Copy code
This completes the basic configuration. The next step is to handle the coverage of various configurations, the complete craco config. JS Configuration File structure, which can be queried in detail in the official document of craco: Configuration File.
be careful! The latest version of craco is V6 4.3 only projects created by cra4 are supported
Build volume analysis
Firstly, the plug-in webpack bundle analyzer is introduced to analyze the composition of the build product
/* 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, // Open browser after construction reportFilename: path.resolve(__dirname, `analyzer/index.html`), }), ], } } Copy code
After packaging with the yarn build command, you can get an analysis diagram containing the components of each chunk.
You can see that the package volume of the project here is as high as 24M, and a lot of duplicate files are packaged.
Code splitting to reduce repeated packaging
Due to lazy loading, each page corresponds to an independent chunk file. Some frequently used libraries will be repeatedly packaged into each chunk, which increases a lot of volume. Split chunksplugin is used here to split these libraries into a single chunk.
In craco, you can get the configuration object of webpack through the configure attribute, modify it to configure, and split the duplicate packages.
Through the analysis of the graph, it is found that jsoneeditor, echarts, antv and other libraries have a great impact on the package volume, so they are separated. In addition to splitting the repeatedly packaged content, we can also extract the basic framework of the project into a separate file base JS, this file contains the basic running environment of all web pages. (for long-term cache of base.js file)
webpack: { plugins: [/** */], configure: (webpackConfig, { env: webpackEnv, paths }) => { webpackConfig.optimization.splitChunks = { ...webpackConfig.optimization.splitChunks, cacheGroups: { base: { // Basic framework 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', // Pack the modules shared by more than two chunk s into the commons group. minChunks: 2, name: 'commons', priority: 80, }, }, }; return webpackConfig; }, } Copy code
After it is separated, the package volume is directly reduced to 7.61M, which is significantly improved.
Load large volume libraries on demand
From the optimized analysis diagram, I found a large library BizCharts, which actually uses only a few components in the project
In this case, you can modify the import method to import on demand.
import { Chart, Axis, Legend, Tooltip } from 'bizcharts'; // Change to manual on-demand import import Chart from 'bizcharts/lib/components/Chart' import Axis from 'bizcharts/lib/components/Axis' import ...... Copy code
It is very troublesome to modify all the introductions manually. At this time, we can use the babel plug-in to help us modify them during construction.
Babel plugin import plug-in was originally used to introduce antd on demand, but here we can also use it for other libraries
babel: { plugins: [ [ 'import', { libraryName: 'bizcharts', libraryDirectory: 'lib/components' }, ], ], } Copy code
Construction speed optimization
The HardSourceWebpackPlugin plug-in can provide intermediate caching for modules. The first build time has not changed much, but the second start can save about 80% of the build time.
In my project, the initial construction speed is 26s and 15s after configuring the plug-in to generate cache, saving more than 60% of the time.
Attach configuration
// 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: { // Basic framework 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', // Pack the modules shared by more than two chunk s into the commons group. minChunks: 2, name: 'commons', priority: 80, }, }, }; return webpackConfig; }, }, babel: { plugins: [ [ // antd's on-demand loading and automatic introduction of style files 'import', { libraryName: 'antd', libraryDirectory: 'es', style: true, }, ], // On demand loading of bizcharts ['import', { libraryName: 'bizcharts', libraryDirectory: 'lib/components' }, 'biz'], ], }, plugins: [ { // Modify antd theme plugin: CracoLessPlugin, options: { lessLoaderOptions: { lessOptions: { math: 'always', modifyVars: { '@primary-color': '#1890ff ', / / theme color }, javascriptEnabled: true, }, }, }, }, ], }; Copy code
summary
This optimization is mainly aimed at reducing the volume of the construction product. The volume is about 24m - > 6.8m, and the improvement is still very large.
Through code segmentation, reduce the repeated packaging of libraries, load some large libraries on demand, and improve the construction speed through some cached plug-ins.
last
If you think this article is a little helpful to you, give it a compliment. Or you can join my development exchange group: 1025263163 learn from each other, and we will have professional technical Q & A to solve doubts
If you think this article is useful to you, please click star: http://github.crmeb.net/u/defu esteem it a favor!
PHP learning manual: https://doc.crmeb.com
Technical exchange forum: https://q.crmeb.com