共计 5137 个字符,预计需要花费 13 分钟才能阅读完成。
Create React App(以下简称 CRA)是一个官网反对的创立 React 单页利用的脚手架,它提供了一个零配置的古代构建设置,将一些简单工具(比方 webpack,Babel)的配置封装了起来,让使用者不必关怀这些工具的具体配置,从而升高了工具的应用难度。
创立办法
npx: npx 来自 npm 5.2+ 或更高版本
npx create-react-app my-app
npm: npm init <initializer>
在 npm 6+ 中可用
npm init react-app my-app
Yarn: yarn create
在 Yarn 0.25+ 中可用
yarn create react-app my-app
Scripts
在新创建的我的项目中,能够运行一些内置命令:
npm start
或 yarn start
在开发模式下运行应用程序, 默认在浏览器关上http://localhost:3000
。如果更改代码,页面将主动从新加载。
npm test
或 yarn test
以交互模式运行测试程序。默认状况下,运行与上次提交后更改的文件相干的测试。
npm run build
或 yarn build
将生产环境的应用程序构建到 build
目录。它能将 React 正确地打包为生产模式中并优化构建以获得最佳性能。构建将被压缩,文件名中将蕴含哈希。
npm run eject
留神:这是单向操作。一旦 eject
,就不能回去了!
执行完这个命令后会将封装在 CRA 中的配置全副反编译到以后我的项目,这样开发者齐全获得 webpack 文件的控制权,能够自定义批改 webpack 打包配置。
文件构造
创立后,我的项目文件构造如下所示:
my-app
node_modules
public
favicon.ico
index.html // 页面模板
manifest.json
src
App.css
App.js
App.test.js
index.css
index.js // 我的项目入口
logo.svg
reportWebVitals.js
setupTests.js
.gitignore
package.json
README.md
yarn.lock
- 为了放慢从新构建的速度,Webpack 只解决
src
中的文件。你须要 将任何 JS 和 CSS 文件放在src
中,否则 Webpack 将发现不了它们。 - 只能在
public/index.html
中应用public
中的文件。 - manifest.js: 目标是将 Web 利用程序安装到设施的主屏幕,为用户提供更快的拜访和更丰盛的体验。
我的项目降级
Create React App 分为两个包:
create-react-app
是一个全局命令行实用程序,可用于创立新我的项目。react-scripts
蕴含 Create React App 的脚本与配置
当你运行 create-react-app
时,它始终应用最新版本的 react-scripts
创立我的项目,新创建的利用会取得所有新性能和改良。
CRA 将所有新个性委托给 react-scripts
, 只须要更新 react-scripts
,不须要更新 create-react-app
就能够降级 CRA 的个性。比方用老版本 CRA 创立了一个我的项目,这个我的项目不具备 PWA 性能,但只有我的项目降级了react-scripts
包的版本就能够具备 PWA 的性能,我的项目自身的代码不须要做任何批改。
如何扩大 Create React App 的 Webpack 配置
Create React App 曾经封装了 webpack 配置,如果想对 webpack 配置做一些批改,这个时候应该怎么办呢?CRA 提供了以下几种形式来批改 webpack 的配置:
- eject 命令
- 替换 react-scripts 包
- 应用 react-app-rewired
- scripts 包 + override 组合
eject 命令
应用 CRA 创立完我的项目当前,在 package.json
外面提供了这样一个命令:
{
...
"scripts": {"eject": "react-scripts eject"},
...
}
执行 yarn eject
后会将封装在 CRA 中的配置全副复制到以后我的项目。eject 后我的项目根目录下会新增 config 与 scripts 文件夹,批改 package.json 与 yarn.lock 文件。
config
jest
env.js
getHttpsConfig.js
modules.js
paths.js
pnpTs.js
webpack.config.js
webpackDevServer.config.js
scripts
build.js
start.js
test.js
如果应用了 eject
命令,尽管扩大了 webpack 配置,然而再也享受不到 CRA 降级带来的益处了。因为 react-scripts
曾经是以文件的模式存在于你的我的项目,而不是以包的模式,所以无奈对其降级。
替换 react-scripts 包
react-scripts 是 CRA 的一个外围包,一些脚本和工具的默认配置都集成在外面,应用 CRA 创立我的项目默认就是应用这个包。然而 CRA 还提供了另外一种形式来创立 CRA 我的项目,用自定义 scripts 包的形式。
// 默认形式
$ create-react-app my-app
// 自定义 scripts 包形式
$ create-react-app my-app --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
react-app-rewired 是 react 社区开源的一个批改 CRA 配置的工具,这种形式让开发者既不必 eject
我的项目也不必本人创立 scripts 包就能够拓展 webpack。
如何应用 react-app-rewired
1. 在 CRA 创立的我的项目中装置react-app-rewired
npm install react-app-rewired --save-dev
2. 在我的项目根目录下创立config-overrides.js
文件(反对自定义文件门路)
/* config-overrides.js */
module.exports = function override(config, env) {
// 参数中的 config 就是默认的 webpack config
// 对 config 进行任意批改
config.mode = 'development';
// 肯定要把新的 config 返回
return config;
}
config-overriders.js
导出的是一个函数,这个函数的签名是 const override = (oldWebpackConfig, env) => newWebpackConfig
。
3. 批改 scripts
命令
/* package.json */
"scripts": {
- "start": "react-scripts start",
+ "start": "react-app-rewired start",
- "build": "react-scripts build",
+ "build": "react-app-rewired build",
- "test": "react-scripts test",
+ "test": "react-app-rewired test",
"eject": "react-scripts eject"
}
config-overrides.js 文件
设置自定义门路 通过 package.json 的config-overrides-path
设置自定义门路:
/* package.json */
{
...
"config-overrides-path": "src/app", // src/app/config-overrides.js
...
}
默认状况下,config-overrides.js
文件导出一个函数,用于自定义 Webpack 配置以在开发或生产模式下编译 React 利用。也能够改为此文件导出一个对象,该对象最多蕴含三个字段,每个字段都是一个函数。
module.exports = {
// The Webpack config
webpack: function(config, env) {
// ...add your webpack config
return config;
},
// The Jest config
jest: function(config) {
// ...add your jest config customisation...
return config;
},
// create a webpack dev server
devServer: function(configFunction) {return function(proxy, allowedHost) {const config = configFunction(proxy, allowedHost);
const fs = require('fs');
config.https = {key: fs.readFileSync(process.env.REACT_HTTPS_KEY, 'utf8'),
cert: fs.readFileSync(process.env.REACT_HTTPS_CERT, 'utf8'),
ca: fs.readFileSync(process.env.REACT_HTTPS_CA, 'utf8'),
passphrase: process.env.REACT_HTTPS_PASS
};
return config;
};
},
paths: function(paths, env) {
// ...add your paths config
return paths;
},
}
实现原理
编译时,react-app-rewired 会先取到 create-react-app 生成的默认的 webpack config,而后调用 override(config)
办法,对 config 进行批改,失去新的 webpack config。webpack 最终会应用这个新的 config 进行打包。
流程大抵如下:
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 包 + override 组合
尽管 react-app-rewired
的形式曾经能够很不便地批改 webpack 的配置了,但也能够在自定义的 script 包中实现相似的性能。
以 build.js
为例,在获取根本 webpack 配置对象和应用 webpack 对象之间退出以下代码:
// 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 对象。