create-react-app 扩展webpack的方法

如何扩展 Create React App 的 Webpack 配置

Create React App(以下简称 CRA)是创建 React 应用的一个脚手架,它与其他脚手架不同的一个地方就是将一些复杂工具(比如 webpack)的配置封装了起来,让使用者不用关心这些工具的具体配置,从而降低了工具的使用难度。

但是对于一些熟悉 webpack 的开发者来说,他们可能想对 webpack 配置做一些修改,这个时候应该怎么办呢?

其实我们可以通过以下几种方式来修改 webpack 的配置:

  • 项目 eject
  • 替换 react-scripts 包
  • 使用 react-app-rewired
  • scripts 包 + override 组合

下面对这几种方式分别进行介绍。

项目 eject

使用 CRA 创建完项目以后,项目在package.json里面提供了这样一个命令:

1
2
3
4
5
6
7
{
  ...
  "scripts": {
    "eject": "react-scripts eject"
  },
  ...
}

执行完这个命令——yarn run eject后会将封装在 CRA 中的配置全部反编译到当前项目,这样用户就可以完全取得 webpack 文件的控制权,想怎么修改就怎么修改了。

1
2
3
4
5
6
7
8
9
10
11
# eject 后项目根目录下会出现 config 文件夹,里面就包含了 webpack 配置
config
├── env.js
├── jest
│   ├── cssTransform.js
│   └── fileTransform.js
├── paths.js
├── polyfills.js
├── webpack.config.dev.js // 开发环境配置
├── webpack.config.prod.js // 生产环境配置
└── webpackDevServer.config.js

CRA 与其他脚手架不同的另一个地方,就是可以通过升级其中的react-scripts包来升级 CRA 的特性。比如用老版本 CRA 创建了一个项目,这个项目不具备 PWA 功能,但只要项目升级了react-scripts包的版本就可以具备 PWA 的功能,项目本身的代码不需要做任何修改。

但如果我们使用了eject命令,就再也享受不到 CRA 升级带来的好处了,因为react-scripts已经是以文件的形式存在于你的项目,而不是以包的形式,所以无法对其升级。

替换 react-scripts 包

react-scripts 是 CRA 的一个核心包,一些脚本和工具的默认配置都集成在里面,使用 CRA 创建项目默认就是使用这个包,但是 CRA 还提供了另外一种方式来创建 CRA 项目,即使用自定义 scripts 包的方式。

1
2
3
4
5
# 默认方式
$ create-react-app foo

# 自定义 scripts 包方式
$ create-react-app foo --scripts-version 自定义包

自定义包可以是下面几种形式:

  • react-scripts包的版本号,比如0.8.2,这种形式可以用来安装低版本的react-scripts包。
  • 一个已经发布到 npm 仓库上的包的名字,比如your-scripts,里面包含了修改过的 webpack 配置。
  • 一个 tgz 格式的压缩文件,比如/your/local/scripts.tgz,通常是未发布到 npm 仓库的自定义 scripts 包,可以用 npm pack 命令生成。

这种方式相对于之前的eject是一种更灵活地修改 webpack 配置的方式,而且可以做到和 CRA 一样,通过升级 scrips 包来升级项目特性。

自定义 scripts 包的结构可以参照react-scripts包的结构,只要修改对应的 webpack 配置文件,并安装上所需的 webpack loader 或 plugin 包就可以了。

使用 react-app-rewired

虽然有这两种方式可以扩展 webpack 配置,但是很多开发者还是觉得太麻烦,有没有一种方式可以既不用eject项目又不用创建自己的 scripts 包呢?答案是肯定的,react-app-rewired 是 react 社区开源的一个修改 CRA 配置的工具。

在 CRA 创建的项目中安装了react-app-rewired后,可以通过创建一个config-overrides.js文件来对 webpack 配置进行扩展。

1
2
3
4
5
6
/* config-overrides.js */

module.exports = function override(config, env) {
  //do stuff with the webpack config...
  return config;
}

override方法的第一个参数config就是 webpack 的配置,在这个方法里面,我们可以对 config 进行扩展,比如安装其他 loader 或者 plugins,最后再将这个 config 对象返回回去。

最后再修改package.json中的脚本命令,修改内容请见这里

scripts 包 + override 组合

虽然react-app-rewired的方式已经可以很方便地修改 webpack 的配置了,但其实我们也可以在自定义的 script 包中实现类似的功能。

react-app-rewired的源码中可以看到它核心的包也叫 react-app-rewired,里面重新覆盖了react-scripts中的几个脚本文件,包括build.jsstart.jstest.js

具体过程是怎样的呢?以build.js为例:

  • 先获取 webpack 的基本配置,然后再调用config-overrides.js(就是在根目录中新增的那个文件)中的override方法,将原先的 webpack 对象作为参数传入,
  • 再取得经过修改后的 webpack 配置对象
  • 最后再调用react-scripts中的build.js脚本,传入修改后的 webpack 对象来执行命令,

具体源码如下:

1
2
3
4
5
6
7
8
9
10
const overrides = require('../config-overrides');
const webpackConfigPath = paths.scriptVersion + "/config/webpack.config.prod";

// load original config
const webpackConfig = require(webpackConfigPath);
// override config in memory
require.cache[require.resolve(webpackConfigPath)].exports =
  overrides.webpack(webpackConfig, process.env.NODE_ENV);
// run original script
require(paths.scriptVersion + '/scripts/build');

知道了原理之后,我们也可以修改自定义 scripts 包的脚本文件,还是以build.js为例,在获取基本 webpack 配置对象和使用 webpack 对象之间加入以下代码:

1
2
3
4
// override config
const override = require(paths.configOverrides);
const overrideFn = override || ((config, env) => config);
const overrideConfig = overrideFn(config, process.env.NODE_ENV);

overrideConfig就是修改后的 webpack 对象,最后修改调用了 webpack 对象的代码,将原来的 webpack 对象替换成修改后的 webpack 对象。

总结

CRA 是一个非常棒的 React 脚手架工具,但你如果不满足于它的 webpack 默认配置,你可以通过上述几种方式来扩展自己项目的 webpack 配置,这几种方式各有优缺点,可以结合具体的使用场景来选择合适自己的方式。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值