批改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.jsconst 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