如何扩展 Create React App 的 Webpack 配置  
原文地址https://zhaozhiming.github.io/blog/2018/01/08/create-react-app-override-webpack-config/

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 配置,这几种方式各有优缺点,可以结合具体的使用场景来选择合适自己的方式。

如何扩展 Create React App 的 Webpack 配置的更多相关文章

  1. 深入 Create React App 核心概念

    本文差点难产而死.因为总结的过程中,多次怀疑本文是对官方文档的直接翻译和简单诺列:同时官方文档很全面,全范围的介绍无疑加深了写作的心智负担.但在最终的梳理中,发现走出了一条与众不同的路,于是坚持分享出 ...

  2. 在 .NET Core 5 中集成 Create React app

    翻译自 Camilo Reyes 2021年2月22日的文章 <Integrate Create React app with .NET Core 5> [1] Camilo Reyes ...

  3. 使用create react app教程

    This project was bootstrapped with Create React App. Below you will find some information on how to ...

  4. tap news:week5 0.0 create react app

    参考https://blog.csdn.net/qtfying/article/details/78665664 先创建文件夹 安装create react app 这个脚手架(facebook官方提 ...

  5. Create React App 安装less 报错

    执行npm run eject 暴露模块 安装 npm i  less less-loader -D 1.打开 react app 的 webpack.config.js const sassRege ...

  6. Create React App

    Facebook开源了React前端框架(MIT Licence),也同时提供了React脚手架 - create-react-app. create-react-app遵循约定优于配置(Coc)的原 ...

  7. create react app的 css loader 进行局部配置

    { test: cssRegex, exclude: cssModuleRegex, use: getStyleLoaders({ importLoaders: 1, sourceMap: isEnv ...

  8. [React] {svg, css module, sass} support in Create React App 2.0

    create-react-app version 2.0 added a lot of new features. One of the new features is added the svgr  ...

  9. [React] Use the Fragment Short Syntax in Create React App 2.0

    create-react-app version 2.0 added a lot of new features. One of the new features is upgrading to Ba ...

随机推荐

  1. Swiper轮播手动后不动

    最近项目首页轮播图用了Swiper轮播,今天突然发现轮播图动画初始正常但是手动换过之后就不动了,解决方法有两种,具体根据采用的情况为准: 1.autoplayDisableOnInteraction: ...

  2. 【ABAP系列】SAP ABAP中将字符格式的金额转换为数值的函数

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP中将字符格式的金 ...

  3. ceph部署问题解决

    注意:1.ceph-deploy实用程序将输出文件到当前目录.执行ceph-deploy时确保你在这个目录下.2.不要使用sudo调用ceph-deploy,要么以root用户身份运行它,因为它不会发 ...

  4. Struts2的核心配置文件

    Struts2的详细配置: 配置的是struts2的核心配置文件:,在struts2的核心配置文件中主要有三个标签需要进行配置:package,action,result. 1. 配置package标 ...

  5. git日常开发中的使用

    作者:python技术人 博客:https://www.cnblogs.com/lpdeboke 1.在远程新建一个仓库,可以使github.gitlib或者bitbucket,这里以bitbucke ...

  6. HDU 6697 Closest Pair of Segments(线段距离)

    首先最容易想到的就是N2暴力枚举所有线段去找最小值,但是这样会做了许多无用功.我们可以先对线段排序,使得线段最左侧的端点按照x轴y轴排序,然后我们可以限定在这个线段的矩形框内的所有线段才有可能产生最小 ...

  7. Oracle 常用统计视图汇总

         Oracle统计信息对数据库性能优化和故障排除都相当重要,目前接触到的与统计信息相关的视图大体有 4 个:   1.v$sysstat 视图      该视图用于记录系统级的统计信息,共 5 ...

  8. wxpython中复选框的基本使用源码实例

    #coding=utf-8 import wx class MyFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self,None,-1, ...

  9. IOC详解

    Ioc--控制反转详解(转载  http://www.cnblogs.com/qinqinmeiren/archive/2011/04/02/2151697.html) 本文转载与百度知道,简单例子让 ...

  10. SSH简单Demo

    web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app version="3 ...