Create React App(如下简称 CRA)是一个官方支持的建立 React 单页应用的脚手架,它提供了一个零配置的现代构建设置,将一些复杂工具(好比 webpack, Babel)的配置封装了起来,让使用者不用关心这些工具的具体配置,从而下降了工具的使用难度。css
npx: npx 来自 npm 5.2+ 或更高版本html
npx create-react-app my-app
npm: npm init <initializer>
在 npm 6+ 中可用node
npm init react-app my-app
Yarn: yarn create
在 Yarn 0.25+ 中可用react
yarn create react-app my-app
在新建立的项目中,能够运行一些内置命令:webpack
npm start
或 yarn start
git
在开发模式下运行应用程序, 默认在浏览器打开http://localhost:3000
。若是更改代码,页面将自动从新加载。github
npm test
或 yarn test
web
以交互模式运行测试程序。 默认状况下,运行与上次提交后更改的文件相关的测试。npm
npm run build
或 yarn build
json
将生产环境的应用程序构建到 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
src
中的文件。 你须要将任何 JS 和 CSS 文件放在 src
中,不然 Webpack 将发现不了它们。public/index.html
中使用 public
中的文件。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 配置,若是想对 webpack 配置作一些修改,这个时候应该怎么办呢?CRA提供了如下几种方式来修改 webpack 的配置:
使用 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 是 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
包。your-scripts
,里面包含了修改过的 webpack 配置。/your/local/scripts.tgz
,一般是未发布到 npm 仓库的自定义 scripts 包,能够用 npm pack
命令生成。这种方式相对于以前的eject
是一种更灵活地修改 webpack 配置的方式,并且能够作到和 CRA 同样,经过升级 scrips 包来升级项目特性。
自定义 scripts 包的结构能够参照react-scripts
包的结构,只要修改对应的 webpack 配置文件,并安装上所需的 webpack loader 或 plugin 包就能够。
react-app-rewired 是 react 社区开源的一个修改 CRA 配置的工具,这种方式让开发者既不用eject
项目也不用本身建立 scripts 包就能够拓展webpack。
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" }
设置自定义路径 经过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');
虽然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 对象。