Repository: timarney/react-app-rewired
Branch: master
Commit: bfe2390b92bb
Files: 36
Total size: 69.8 KB
Directory structure:
gitextract_pn_d18s7/
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── README_zh.md
├── bin/
│ ├── index.js
│ └── jest.js
├── config/
│ ├── paths.js
│ ├── webpack.config.js
│ └── webpackDevServer.config.js
├── config-overrides.js
├── index.js
├── overrides/
│ ├── devServer.js
│ ├── jest.js
│ ├── paths.js
│ └── webpack.js
├── package.json
├── scripts/
│ ├── build.js
│ ├── start.js
│ ├── test.js
│ └── utils/
│ ├── babelTransform.js
│ ├── dependRequire.js
│ ├── paths.js
│ └── rewireJestConfig.js
└── test/
└── react-app/
├── .gitignore
├── README.md
├── config-overrides.js
├── package.json
├── public/
│ ├── index.html
│ └── manifest.json
└── src/
├── App.css
├── App.js
├── App.test.js
├── index.css
├── index.js
└── serviceWorker.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules
jspm_packages
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
build/*
.idea
================================================
FILE: .travis.yml
================================================
language: node_js
node_js:
- "8"
- "10"
cache:
yarn: true
before_script: yarn setup
after_script: yarn teardown
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2016 Tim Arney
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
> ℹ️
Before submitting an issue to this repo - Ensure it's a **issue with the code in this repo**, not a **how do I configure** something with **Webpack** question (post something on Stack Overflow or Spectrum). It's your config you "own" it.
- 🚨Version 2.0 removes the rewire helper functions
- [中文版本说明](./README_zh.md)
[](https://www.npmjs.com/package/react-app-rewired)
[](https://www.npmjs.com/package/react-app-rewired)
Tweak the create-react-app webpack config(s) without using 'eject' and without creating a fork of the react-scripts.
All the benefits of create-react-app without the limitations of "no config". You can add plugins, loaders whatever you need.
# Rewire Your App ☠
As of Create React App 2.0 this repo is "lightly" maintained mostly by the community at this point.
⚠️ **Please Note:**
> By doing this you're breaking the ["guarantees"](https://github.com/facebookincubator/create-react-app/issues/99#issuecomment-234657710) that CRA provides. That is to say you now "own" the configs. **No support** will be provided. Proceed with caution.
"Stuff can break" — Dan Abramov
https://twitter.com/dan_abramov/status/1045809734069170176
**Note:** I personally use [next.js](https://github.com/zeit/next.js/) or [Razzle](https://github.com/jaredpalmer/razzle) which both support custom Webpack out of the box.
## Alternatives
You can try [customize-cra](https://github.com/arackaf/customize-cra) for a set of CRA 2.0 compatible rewirers,
or any of the alternative projects and forks that aim to support 2.0:
- [Rescripts](https://github.com/rescripts/rescripts), an alternative framework for extending CRA configurations (supports 2.0+).
- [react-scripts-rewired](https://github.com/marcopeg/create-react-app/blob/master/packages/react-scripts/README.md) for a fork of this project that aims to support CRA 2.0
- [craco](https://github.com/sharegate/craco)
# How to rewire your create-react-app project
> Create your app using [create-react-app](https://github.com/facebookincubator/create-react-app) and then rewire it.
#### 1) Install react-app-rewired
##### For create-react-app 2.x with Webpack 4:
```bash
npm install react-app-rewired --save-dev
```
##### For create-react-app 1.x or react-scripts-ts with Webpack 3:
```bash
npm install react-app-rewired@1.6.2 --save-dev
```
#### 2) Create a `config-overrides.js` file in the root directory
```javascript
/* config-overrides.js */
module.exports = function override(config, env) {
//do stuff with the webpack config...
return config;
}
```
```
+-- your-project
| +-- config-overrides.js
| +-- node_modules
| +-- package.json
| +-- public
| +-- README.md
| +-- src
```
#### 3) 'Flip' the existing calls to `react-scripts` in `npm` scripts for start, build and test
```diff
/* 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"
}
```
Note: Do NOT flip the call for the `eject` script.
That gets run only once for a project, after which you are given full control over the webpack configuration making `react-app-rewired` no longer required.
There are no configuration options to rewire for the `eject` script.
#### 4) Start the Dev Server
```bash
npm start
```
#### 5) Build your app
```bash
npm run build
```
## Extended Configuration Options
You can set a custom path for `config-overrides.js`. If you (for instance) wanted to use a 3rd-party `config-overrides.js` that exists in `node_modules`, you could add the following to your `package.json`:
```json
"config-overrides-path": "node_modules/some-preconfigured-rewire"
```
By default, the `config-overrides.js` file exports a single function to use when customising the webpack configuration for compiling your react app in development or production mode. It is possible to instead export an object from this file that contains up to three fields, each of which is a function. This alternative form allows you to also customise the configuration used for Jest (in testing), and for the Webpack Dev Server itself.
This example implementation is used to demonstrate using each of the object require functions. In the example, the functions:
* have some tests run conditionally based on `.env` variables
* set the https certificates to use for the Development Server, with the filenames specified in `.env` file variables.
```javascript
module.exports = {
// The Webpack config to use when compiling your react app for development or production.
webpack: function(config, env) {
// ...add your webpack config
return config;
},
// The Jest config to use when running your jest tests - note that the normal rewires do not
// work here.
jest: function(config) {
// ...add your jest config customisation...
// Example: enable/disable some tests based on environment variables in the .env file.
if (!config.testPathIgnorePatterns) {
config.testPathIgnorePatterns = [];
}
if (!process.env.RUN_COMPONENT_TESTS) {
config.testPathIgnorePatterns.push('/src/components/**/*.test.js');
}
if (!process.env.RUN_REDUCER_TESTS) {
config.testPathIgnorePatterns.push('/src/reducers/**/*.test.js');
}
return config;
},
// The function to use to create a webpack dev server configuration when running the development
// server with 'npm run start' or 'yarn start'.
// Example: set the dev server to use a specific certificate in https.
devServer: function(configFunction) {
// Return the replacement function for create-react-app to use to generate the Webpack
// Development Server config. "configFunction" is the function that would normally have
// been used to generate the Webpack Development server config - you can use it to create
// a starting configuration to then modify instead of having to create a config from scratch.
return function(proxy, allowedHost) {
// Create the default config by calling configFunction with the proxy/allowedHost parameters
const config = configFunction(proxy, allowedHost);
// Change the https certificate options to match your certificate, using the .env file to
// set the file paths & passphrase.
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 your customised Webpack Development Server config.
return config;
};
},
// The paths config to use when compiling your react app for development or production.
paths: function(paths, env) {
// ...add your paths config
return paths;
},
}
```
#### 1) Webpack configuration - Development & Production
The `webpack` field is used to provide the equivalent to the single-function exported from config-overrides.js. This is where all the usual rewires are used. It is not able to configure compilation in test mode because test mode does not get run through Webpack at all (it runs in Jest). It is also not able to be used to customise the Webpack Dev Server that is used to serve pages in development mode because create-react-app generates a separate Webpack configuration for use with the dev server using different functions and defaults.
#### 2) Jest configuration - Testing
Webpack is not used for compiling your application in Test mode - Jest is used instead. This means that any rewires specified in your webpack config customisation function _will not be applied_ to your project in test mode.
React-app-rewired automatically allows you to customise your Jest configuration in a `jest` section of your `package.json` file, including allowing you to set configuration fields that create-react-app would usually block you from being able to set. It also automatically sets up Jest to compile the project with Babel prior to running tests. Jest's configuration options are documented separately at the [Jest website](https://facebook.github.io/jest/docs/en/configuration.html). *Note:* Configuration arrays and objects are merged, rather than overwritten. See [#240](https://github.com/timarney/react-app-rewired/issues/240) and [#241](https://github.com/timarney/react-app-rewired/issues/241) for details
If you want to add plugins and/or presets to the Babel configuration that Jest will use, you need to define those plugins/presets in either a `babel` section inside the `package.json` file or inside a `.babelrc` file. React-app-rewired alters the Jest configuration to use these definition files for specifying Babel options when Jest is compiling your react app. The format to use in the Babel section of package.json or the .babelrc file is documented separately at the [Babel website](https://babeljs.io/docs/usage/babelrc/).
The `jest` field in the module.exports object in `config-overrides.js` is used to specify a function that can be called to customise the Jest testing configuration in ways that are not possible in the jest section of the package.json file. For example, it will allow you to change some configuration options based on environment variables. This function is passed the default create-react-app Jest configuration as a parameter and is required to return the modified Jest configuration that you want to use. A lot of the time you'll be able to make the configuration changes needed simply by using a combination of the `package.json` file's jest section and a `.babelrc` file (or babel section in package.json) instead of needing to provide this jest function in `config-overrides.js`.
#### 3) Webpack Dev Server
When running in development mode, create-react-app does not use the usual Webpack config for the Development Server (the one that serves the app pages). This means that you cannot use the normal `webpack` section of the `config-overrides.js` server to make changes to the Development Server settings as those changes won't be applied.
Instead of this, create-react-app expects to be able to call a function to generate the webpack dev server when needed. This function is provided with parameters for the proxy and allowedHost settings to be used in the webpack dev server (create-react-app retrieves the values for those parameters from your package.json file).
React-app-rewired provides the ability to override this function through use of the `devServer` field in the module.exports object in `config-overrides.js`. It provides the devServer function a single parameter containing the default create-react-app function that is normally used to generate the dev server config (it cannot provide a generated version of the configuration because react-scripts is calling the generation function directly). React-app-rewired needs to receive as a return value a _replacement function_ for create-react-app to then use to generate the Development Server configuration (i.e. the return value should be a new function that takes the two parameters for proxy and allowedHost and itself returns a Webpack Development Server configuration). The original react-scripts function is passed into the `config-overrides.js` devServer function so that you are able to easily call this yourself to generate your initial devServer configuration based on what the defaults used by create-react-app are.
#### 4) Paths configuration - Development & Production
The `paths` field is used to provide overrides for the `create-react-app` paths passed into webpack and jest.
#### 5) Provide rewired webpack config for 3rd party tools
Some third party tools, like [`react-cosmos`](https://github.com/react-cosmos/react-cosmos) relies on your webpack config.
You can create `webpack.config.js` file and export rewired config using following snippet:
```js
const { paths } = require('react-app-rewired');
// require normalized overrides
const overrides = require('react-app-rewired/config-overrides');
const config = require(paths.scriptVersion + '/config/webpack.config.dev');
module.exports = overrides.webpack(config, process.env.NODE_ENV);
```
Then just point to this file in tool configuration.
## Additional Issues and Options
#### 1) Entry Point: 'src/index.js'
At this point in time, it is difficult to change the entry point from the default `src/index.js` file due to the way that file is included by create-react-app. The normal rewiring process gets bypassed by several of the create-react-app scripts.
There are three work-arounds available here:
1. Simply require/import your desired file from inside the src/index.js file, like:
```javascript
require('./index.tsx');
```
2. Use a customised version of the react-scripts package that changes the entry point inside the scripts themselves (e.g. [react-scripts-ts](https://github.com/wmonk/create-react-app-typescript) for a typescript project - see below for how to use custom script versions with react-app-rewired).
3. Override the `react-dev-utils/checkRequiredFiles` function to always return true (causing create-react-app to no longer try to enforce that the entry file must exist).
#### 2) Custom scripts versions
It is possible to use a custom version of the `react-scripts` package with react-app-rewired by specifying the name of the scripts package in the command line option `--scripts-version` or setting `REACT_SCRIPTS_VERSION=<...>` via the environment.
A working example for using the scripts version option is:
```json
{
"scripts": {
"start": "react-app-rewired start --scripts-version react-scripts-ts",
"build": "react-app-rewired build --scripts-version react-scripts-ts",
"test": "react-app-rewired test --scripts-version react-scripts-ts",
"eject": "react-scripts eject"
}
}
```
##### React-app-rewired 2.x requires a custom react-scripts package to provide the following files:
* config/env.js
* **config/webpack.config.js**
* config/webpackDevServer.config.js
* scripts/build.js
* scripts/start.js
* scripts/test.js
* scripts/utils/createJestConfig.js
##### React-app-rewired 1.x requires a custom react-scripts package to provide the following files:
* config/env.js
* **config/webpack.config.dev.js**
* **config/webpack.config.prod.js**
* config/webpackDevServer.config.js
* scripts/build.js
* scripts/start.js
* scripts/test.js
* scripts/utils/createJestConfig.js
#### 3) Specify config-overrides as a directory
React-app-rewired imports your config-overrides.js file without the '.js' extension. This means that you have the option of creating a directory called `config-overrides` at the root of your project and exporting your overrides from the default `index.js` file inside that directory.
If you have several custom overrides using a directory allows you to be able to put each override in a separate file. An example template that demonstrates this can be found in [Guria/rewired-ts-boilerplate](https://github.com/Guria/rewired-ts-boilerplate/tree/master/config-overrides) at Github.
#### 4) Specify config-overrides location from command line
If you need to change the location of your config-overrides.js you can pass a command line option --config-overrides to the react-app-rewired script.
# Version 1.X Community Maintained Rewires (Check the plugin repo for 2.0 support)
## Babel plugins
* [react-app-rewire-emotion](https://github.com/osdevisnot/react-app-rewire-contrib/tree/master/packages/react-app-rewire-emotion) by [@osdevisnot](https://github.com/osdevisnot)
* [react-app-rewire-lodash](https://github.com/osdevisnot/react-app-rewire-contrib/tree/master/packages/react-app-rewire-lodash) by [@osdevisnot](https://github.com/osdevisnot)
* [react-app-rewire-styled-components](https://github.com/withspectrum/react-app-rewire-styled-components) by [@mxstbr](https://github.com/mxstbr)
* [react-app-rewire-polished](https://github.com/rawrmonstar/react-app-rewire-polished) by [@rawrmonstar](https://github.com/rawrmonstar)
* [react-app-rewire-idx](https://github.com/viktorivarsson/react-app-rewire-idx) by [@viktorivarsson](https://github.com/viktorivarsson)
* [react-app-rewire-glamorous-displayname](https://github.com/CarlRosell/react-app-rewire-glamorous-displayname) by [@CarlRosell](https://github.com/CarlRosell)
* [react-app-rewire-import](https://github.com/brianveltman/react-app-rewire-import) by [@brianveltman](https://github.com/brianveltman)
* [react-app-rewire-inline-import-graphql-ast](https://github.com/detrohutt/react-app-rewire-inline-import-graphql-ast) by [@detrohutt](https://github.com/detrohutt)
* [react-app-rewire-react-intl](https://github.com/clemencov/react-app-rewire-react-intl) by [@clemencov](https://github.com/clemencov)
* [react-app-rewire-lingui](https://github.com/Andreyco/react-app-rewire-lingui) by [@andreyco](https://github.com/Andreyco)
* [react-app-rewire-date-fns](https://github.com/stk-dmitry/react-app-rewire-date-fns) by [@stk-dmitry](https://github.com/stk-dmitry)
* [react-app-rewired-esbuild](https://github.com/fupengl/react-app-rewired-esbuild) by [@fupengl](https://github.com/fupengl)
## Webpack plugins
* [react-app-rewire-appcache-plugin](https://github.com/lwd-technology/react-app-rewire-appcache-plugin) by [@jtheis85](https://github.com/jtheis85)
* [react-app-rewire-build-dev](https://github.com/raodurgesh/react-app-rewire-build-dev) by [@raodurgesh](https://github.com/raodurgesh)
* [react-app-rewire-define-plugin](https://github.com/lwd-technology/react-app-rewire-define-plugin) by [@jtheis85](https://github.com/jtheis85)
* [react-app-rewire-favicons-plugin](https://github.com/rickycook/react-app-rewire-favicons-plugin) by [@rickycook](https://github.com/rickycook)
* [react-app-rewire-imagemin-plugin](https://github.com/lwd-technology/react-app-rewire-imagemin-plugin) by [@jtheis85](https://github.com/jtheis85)
* [react-app-rewire-modernizr](https://github.com/ctrlplusb/react-app-rewire-modernizr) by [@ctrlplusb](https://github.com/ctrlplusb)
* [react-app-rewire-preload-plugin](https://github.com/lwd-technology/react-app-rewire-preload-plugin) by [@jtheis85](https://github.com/jtheis85)
* [react-app-rewire-provide-plugin](https://github.com/lwd-technology/react-app-rewire-provide-plugin) by [@jtheis85](https://github.com/jtheis85)
* [react-app-rewire-inline-source](https://github.com/marcopeg/react-app-rewire-inline-source) by [@marcopeg](https://github.com/marcopeg)
* [react-app-rewire-webpack-bundle-analyzer](https://github.com/byzyk/react-app-rewire-webpack-bundle-analyzer) by [@byzyk](https://github.com/byzyk)
* [react-app-rewire-unplug](https://github.com/sigged/react-app-rewire-unplug) by [@sigged](https://github.com/sigged)
* [react-app-rewire-compression-plugin](https://github.com/ArVan/react-app-rewire-compression-plugin) by [@ArVan](https://github.com/ArVan)
* [react-app-rewire-multiple-entry](https://github.com/Derek-Hu/react-app-rewire-multiple-entry) by [@Derek](https://github.com/Derek-Hu)
## Loaders
* [react-app-rewire-postcss](https://github.com/csstools/react-app-rewire-postcss)
* [react-app-rewire-nearley](https://github.com/lwd-technology/react-app-rewire-nearley) by [@jtheis85](https://github.com/jtheis85)
* [react-app-rewire-coffeescript](https://github.com/stevefan1999/react-app-rewire-coffeescript) by [@stevefan1999](https://github.com/stevefan1999)
* [react-app-rewire-typescript](https://github.com/lwd-technology/react-app-rewire-typescript) by [@jtheis85](https://github.com/jtheis85)
* [react-app-rewire-typescript-babel-preset](https://github.com/strothj/react-app-rewire-typescript-babel-preset) by [@strothj](https://github.com/strothj)
* [react-app-rewire-css-modules](https://github.com/codebandits/react-app-rewire-css-modules) by [@lnhrdt](https://github.com/lnhrdt)
* [react-app-rewire-css-modules-extensionless](https://github.com/moxystudio/react-app-rewire-css-modules-extensionless) by [@moxystudio](https://github.com/moxystudio)
* [react-app-rewire-less-modules](https://github.com/andriijas/react-app-rewire-less-modules) by [@andriijas](https://github.com/andriijas)
* [react-app-rewire-stylus-modules](https://github.com/marcopeg/react-app-rewire-stylus-modules) by [@marcopeg](https://github.com/marcopeg)
* [react-app-rewire-svg-react-loader](https://github.com/codebandits/react-app-rewire-svg-react-loader) by [@lnhrdt](https://github.com/lnhrdt)
* [react-app-rewire-bem-i18n-loader](https://github.com/maxvipon/react-app-rewire-bem-i18n-loader) by [@maxvipon](https://github.com/maxvipon)
* [react-app-rewire-babel-loader](https://github.com/dashed/react-app-rewire-babel-loader) by [@dashed](https://github.com/dashed)
* [react-app-rewire-svgr](https://github.com/gitim/react-app-rewire-svgr) by [@gitim](https://github.com/gitim)
* [react-app-rewire-yaml](https://github.com/hsz/react-app-rewire-yaml) by [@hsz](https://github.com/hsz)
* [react-app-rewire-scss](https://github.com/aze3ma/react-app-rewire-scss) by [@aze3ma](https://github.com/aze3ma)
* [react-app-rewire-scss-loaders](https://github.com/iSanchezDev/react-app-rewire-scss-loaders) by [@isanchez](https://github.com/isanchezdev)
* [react-app-rewire-external-svg-loader](https://github.com/moxystudio/react-app-rewire-external-svg-loader) by [@moxystudio](https://github.com/moxystudio)
* [react-app-rewire-typings-for-css-module](https://github.com/rainx/react-app-rewire-typings-for-css-module) by [@rainx](https://github.com/rainx)
## Other
* [react-app-rewire-create-react-library](https://github.com/osdevisnot/react-app-rewire-create-react-library) by [@osdevisnot](https://github.com/osdevisnot)
* [react-app-rewire-react-library](https://github.com/osdevisnot/react-app-rewire-contrib/tree/master/packages/react-app-rewire-react-library) by [@osdevisnot](https://github.com/osdevisnot)
* [react-app-rewire-vendor-splitting](https://github.com/andriijas/react-app-rewire-vendor-splitting) by [@andriijas](https://github.com/andriijas)
* [react-app-rewired with Inferno](packages/react-app-rewired/examples/inferno.md)
* [react-app-rewired with react-styleguideist](packages/react-app-rewired/examples/react-styleguidist.md)
* [react-app-rewired with react-hot-loader](https://github.com/cdharris/react-app-rewire-hot-loader) by [@cdharris](https://github.com/cdharris)
* [react-app-alias](https://github.com/oklas/react-app-alias) by [@oklas](https://github.com/oklas)
* [react-app-rewire-aliases](https://github.com/aze3ma/react-app-rewire-aliases) by [@aze3ma](https://github.com/aze3ma)
* [react-app-rewire-blockstack](https://github.com/harrysolovay/react-app-rewire-blockstack) by [@harrysolovay](https://github.com/harrysolovay)
* [ideal-rewires](https://github.com/harrysolovay/ideal-rewires) by [@harrysolovay](https://github.com/harrysolovay)
* [react-app-rewire-yarn-workspaces](https://github.com/viewstools/yarn-workspaces-cra-crna/tree/master/react-app-rewire-yarn-workspaces) by [@viewstools](https://github.com/viewstools)
* [react-app-rewired-single-spa](https://github.com/fupengl/react-app-rewired-single-spa) by [@fupengl](https://github.com/fupengl)
# Development
When developing this project, ensure you have [yarn](https://yarnpkg.com/en/docs/install) installed.
## Quick Start
To run the test app, navigate to the directory and run:
```bash
yarn setup
yarn start
```
(when you are finished, run `yarn teardown` to clean up)
## Commands
Here is a list of all the available commands to help you in development
- `yarn setup` - installs dependences and links `test/react-app`
- `yarn start` - starts the react app
- `yarn build` - builds the react app
- `yarn test` - tests the react app
- `yarn teardown` - unlinks `test/react-app` and removes dependencies
# Why This Project Exists
See: [Create React App — But I don’t wanna Eject.](https://medium.com/@timarney/but-i-dont-wanna-eject-3e3da5826e39#.x81bb4kji)
================================================
FILE: README_zh.md
================================================
> ℹ️
请在提 issue 之前确保 **issue 是关于项目代码**,而不是 **我要怎么配置 Webpack**。(配置相关的问题可以在 Stack Overflow 或者 Spectrum 上提问)。
- 🚨 2.0版本移除了rewire helper 功能
[](https://www.npmjs.com/package/react-app-rewired)
[](https://www.npmjs.com/package/react-app-rewired)
此工具可以在不 'eject' 也不创建额外 react-scripts 的情况下修改 create-react-app 内置的 webpack 配置,然后你将拥有 create-react-app 的一切特性,且可以根据你的需要去配置 webpack 的 plugins, loaders 等。
# Rewire你的应用 ☠
从 Create React App 2.0开始,这个仓库主要由社区“轻度”维护。
⚠️ **注意**
> 使用了 react-app-rewired 之后,等于你得到了项目的配置权,但这表示你的项目将无法得到 CRA 提供的配置“[保证](https://github.com/facebookincubator/create-react-app/issues/99#issuecomment-234657710)”,希望你知道自己要做什么。
"Stuff can break" — Dan Abramov https://twitter.com/dan_abramov/status/1045809734069170176
**注意:** 我个人使用[next.js](https://github.com/zeit/next.js/) 或者 [Razzle](https://github.com/jaredpalmer/razzle) 都支持开箱即用的自定义 Webpack。
## 备选方案
您可以尝试使用 [customize-cra](https://github.com/arackaf/customize-cra) 来获得一组 CRA 2.0兼容的 rewirers,或任何旨在支持2.0的替代项目和分支:
- [Rescripts](https://github.com/rescripts/rescripts),用于扩展 CRA 配置的替代框架(支持2.0+)
- [react-scripts-rewired](https://github.com/marcopeg/create-react-app/blob/master/packages/react-scripts/README.md) 为该项目的一个分支,旨在支持 CRA 2.0
- [craco](https://github.com/sharegate/craco)
# 如何rewire create-react-app项目
> 使用 [create-react-app](https://github.com/facebookincubator/create-react-app) 创建您的应用,然后 rewire
#### 1) 安装 react-app-rewired
##### 对于使用 Webpack 4 的 create-react-app 2.x
```bash
$ npm install react-app-rewired --save-dev
```
##### 对于 create-react-app 1.x 或 react-scripts-ts 与 Webpack 3:
```bash
$ npm install react-app-rewired@1.6.2 --save-dev
```
#### 2) 在根目录中创建一个 config-overrides.js 文件
```javascript
/* config-overrides.js */
module.exports = function override(config, env) {
//do stuff with the webpack config...
return config;
}
```
```
+-- your-project
| +-- config-overrides.js
| +-- node_modules
| +-- package.json
| +-- public
| +-- README.md
| +-- src
```
#### 3) 替换 package.json 中 scripts 执行部分
```diff
/* 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 --env=jsdom",
+ "test": "react-app-rewired test --env=jsdom",
"eject": "react-scripts eject"
}
```
注意:不用替换 `eject` 部分。工具中没有针对 `eject` 的配置替换,执行了 eject 命令会让工具失去作用(能找到这个插件我也相信你知道 eject 是干嘛的)。
#### 4) 启动 Dev Server
```bash
$ npm start
```
#### 5) 构建你的应用程序
```bash
$ npm run build
```
## 扩展配置选项
您可以为其设置自定义路径 `config-overrides.js`
如果您想要使用在 `node_modules` 中的第三方 config-overrides.js,您可以将以下内容添加到您的`package.json`:
```json
"config-overrides-path": "node_modules/some-preconfigured-rewire"
```
默认情况下,该 `config-overrides.js` 文件导出单个函数,以便在开发或生产模式下自定义 webpack 配置, 方便编译您的 react 应用程序。可以从该文件中导出一个包含最多三个字段的对象,每个字段都是一个函数。这种替代形式允许您自定义用于 Jest(在测试中)和 Webpack Dev Server 本身的配置。
此示例实现用于演示使用每个对象需要的函数。在此示例中,展示的功能是:
* 根据 `.env` 变量有条件地运行一些测试
* 设置用于 Development Server 的 https 证书,`.env` 文件变量中指定的文件名。
```javascript
module.exports = {
// The Webpack config to use when compiling your react app for development or production.
webpack: function(config, env) {
// ...add your webpack config
return config;
},
// The Jest config to use when running your jest tests - note that the normal rewires do not
// work here.
jest: function(config) {
// ...add your jest config customisation...
// Example: enable/disable some tests based on environment variables in the .env file.
if (!config.testPathIgnorePatterns) {
config.testPathIgnorePatterns = [];
}
if (!process.env.RUN_COMPONENT_TESTS) {
config.testPathIgnorePatterns.push('/src/components/**/*.test.js');
}
if (!process.env.RUN_REDUCER_TESTS) {
config.testPathIgnorePatterns.push('/src/reducers/**/*.test.js');
}
return config;
},
// The function to use to create a webpack dev server configuration when running the development
// server with 'npm run start' or 'yarn start'.
// Example: set the dev server to use a specific certificate in https.
devServer: function(configFunction) {
// Return the replacement function for create-react-app to use to generate the Webpack
// Development Server config. "configFunction" is the function that would normally have
// been used to generate the Webpack Development server config - you can use it to create
// a starting configuration to then modify instead of having to create a config from scratch.
return function(proxy, allowedHost) {
// Create the default config by calling configFunction with the proxy/allowedHost parameters
const config = configFunction(proxy, allowedHost);
// Change the https certificate options to match your certificate, using the .env file to
// set the file paths & passphrase.
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 your customised Webpack Development Server config.
return config;
};
},
// The paths config to use when compiling your react app for development or production.
paths: function(paths, env) {
// ...add your paths config
return paths;
},
}
```
#### 1) Webpack 配置 - 开发和生产
该 `webpack` 字段用于提供与 config-overrides.js 导出的单个函数的等效项。这是使用所有常用 rewire 的地方。它无法在测试模式下配置编译,因为测试模式根本无法通过 Webpack 运行(它在 Jest 中运行)。它也不能用于自定义用于在开发模式下提供页面的 Webpack Dev Server,因为 create-react-app 生成一个单独的 Webpack 配置,以便与使用不同函数和默认配置的 dev 服务器一起使用。
#### 2) Jest 配置 - 测试
Webpack 不用于在测试模式下编译应用程序 - 而是使用 Jest。这意味着您的 webpack 配置自定义函数中指定的任何重连接*都不会在*测试模式下应用于您的项目。
React-app-rewired 自动允许您在文件的某个 `jest` 部分自定义 Jest 配置 `package.json`,包括允许您设置在 create-react-app 通常会阻止您进行设置的配置字段。它还会自动设置 Jest,以便在运行测试之前使用 Babel 编译项目。Jest 的配置选项在 [Jest 网站](https://facebook.github.io/jest/docs/en/configuration.html)上单独记录。*注意*:配置数组和对象是合并的,而不是被覆盖。有关详细信息,请参阅[#240](https://github.com/timarney/react-app-rewired/issues/240)和[#241](https://github.com/timarney/react-app-rewired/issues/241)
如果想要将 Jest 插件或预设添加到 Babel 配置中,则需要在 `package.json` 文件内部里的`babel`定义关于这些插件/预设。或者是在 `.babelrc` 中去定义。React-app-rewired 改变了 Jest 配置,以便在 Jest 编译您的 react 应用程序时使用这些定义文件来指定 Babel 选项。在 [Babel 网站](https://babeljs.io/docs/usage/babelrc/)上单独记录了在 `package.json` 的 Babel 部分中或 `.babelrc` 使用的格式。
`jest` 在 module.exports 对象中的字段 `config-overrides.js` 用于指定可以调用的函数,以便以 package.json 文件的 jest 部分中不能的方式自定义 Jest 测试配置。例如,它允许您根据环境变量更改某些配置选项。此函数作为参数传递默认的 create-react-app Jest 配置,并且需要返回要使用的已修改的Jest配置。很多时候你只需要使用 package.json 文件的 jest 部分和 `.babelrc` 文件(或 `package.json` 中的 babel 部分)的组合就可以进行配置更改,而不需要提供这个 jest 函数 `config-overrides.js`
#### 3) Webpack Dev Server
在开发模式下运行时,create-react-app 不会为 Development Server(提供应用程序页面的服务器)使用常用 Webpack 配置。这意味着您无法使用服务器的常规 `webpack` 在`config-overrides.js` 中的部分来更改 Development Server 设置,因为这些更改将不会应用。
与此相反,create-react-app 期望能够在需要时调用函数来生成 webpack dev 服务器。此函数提供了在 webpack dev 服务器中使用的 proxy 和 allowedHost 设置的参数(create-react-app 从package.json 文件中检索这些参数的值)。
React-app-rewired 提供了通过使用在 `config-overrides.js` 文件里 module.exports 出的对象 `devServer` 来覆盖此函数。它为 devServer 函数提供了一个包含默认 create-react-app 函数的参数,该函数通常用于生成 dev server 配置(它不能提供生成的配置版本,因为 react-scripts 直接调用生成函数)。React-app-rewired 需要接收 create-react-app 的*替换函数*作为返回值,然后用于生成 Development Server 配置(即返回值应该是一个新函数,它接受 proxy 和 allowedHost 的两个参数和本身作为参数,并返回 Webpack Development Server 配置)。原始的 react-scripts 函数被传递给`config-overrides.js` 中 devServer 函数,以便您可以自己轻松调用此方法,根据 create-react-app 使用的默认值生成初始 devServer 配置。
#### 4) 路径配置 - 开发&生产
该 `paths` 字段用于为 `create-react-app` 传递到 webpack 和 jest 的路径提供覆盖。
#### 5) 为第三方工具提供 rewired 的 webpack 配置
一些第三方工具,比如 [react-cosmos](https://github.com/react-cosmos/react-cosmos) 依赖于你的 webpack 配置。您可以创建 `webpack.config.js` 文件,通过下列代码导出 rewired 配置:
```js
const { paths } = require('react-app-rewired');
// require normalized overrides
const overrides = require('react-app-rewired/config-overrides');
const config = require(paths.scriptVersion + '/config/webpack.config.dev');
module.exports = overrides.webpack(config, process.env.NODE_ENV);
```
然后在工具配置中指向此文件。
## 其他问题和选择
#### 1) 入口: 'src/index.js'
此时,由于 create-react-app 包含该文件的方式,很难从默认文件 `src/index.js` 更改入口点。几个 create-react-app 脚本绕过了正常的 rewiring 过程。
这里有三种解决方法:
1. 只需要从 src / index.js 文件中输入/导入所需的文件,例如:
```javascript
require('./index.tsx');
```
2. 使用自定义版本的 react-scripts 包来更改脚本本身内部的入口点 (例如. [react-scripts-ts](https://github.com/wmonk/create-react-app-typescript) 对于typescript项目 - 请参阅下面有关如何使用 react-app-rewired 的自定义脚本版本).
3. 重写 `react-dev-utils/checkRequiredFiles` 函数以始终返回 true(导致 create-react-app 不再尝试强制条目文件必须存在)
#### 2) 自定义脚本版本
`react-scripts` 通过在命令行选项中指定脚本包的名称 `--scripts-version` 或 `REACT_SCRIPTS_VERSION=<...>` 通过环境进行设置,可以使用自定义版本的包和react-app-rewired。
使用脚本版本选项的工作示例是:
```json
{
"scripts": {
"start": "react-app-rewired start --scripts-version react-scripts-ts",
"build": "react-app-rewired build --scripts-version react-scripts-ts",
"test": "react-app-rewired test --scripts-version react-scripts-ts --env=jsdom",
"eject": "react-scripts eject"
}
}
```
##### React-app-rewired 2.x 需要一个自定义的 react-scripts 包来提供以下文件:
* config/env.js
* **config/webpack.config.js**
* config/webpackDevServer.config.js
* scripts/build.js
* scripts/start.js
* scripts/test.js
* scripts/utils/createJestConfig.js
##### React-app-rewired 1.x 需要一个自定义的 react-scripts 包来提供以下文件:
* config/env.js
* **config/webpack.config.dev.js**
* **config/webpack.config.prod.js**
* config/webpackDevServer.config.js
* scripts/build.js
* scripts/start.js
* scripts/test.js
* scripts/utils/createJestConfig.js
#### 3) 将 config-overrides 指定为目录
React-app-rewired 会导入您的 config-overrides.js 文件而不使用 “.js” 扩展名。这意味着您可以选择创建一个名为 `config-overrides` 的目录在你的根目录中,并从该 `index.js` 目录中的默认文件中导出覆盖。
如果使用目录有多个自定义覆盖,则允许您将每个覆盖放在单独的文件中。演示这一点的示例模板可以在 Github 的 [Guria / rewired-ts-boilerplate](https://github.com/Guria/rewired-ts-boilerplate/tree/master/config-overrides) 中找到。
#### 4) 从命令行指定config-overrides位置
如果需要更改 config-overrides.js 的位置,可以将命令行选项 --config-overrides 给 react-app-rewired 脚本。
# 版本1.X社区维护 Rewires(检查插件仓库是否支持2.0)
## Babel 插件
* [react-app-rewire-emotion](https://github.com/osdevisnot/react-app-rewire-contrib/tree/master/packages/react-app-rewire-emotion) by [@osdevisnot](https://github.com/osdevisnot)
* [react-app-rewire-lodash](https://github.com/osdevisnot/react-app-rewire-contrib/tree/master/packages/react-app-rewire-lodash) by [@osdevisnot](https://github.com/osdevisnot)
* [react-app-rewire-styled-components](https://github.com/withspectrum/react-app-rewire-styled-components) by [@mxstbr](https://github.com/mxstbr)
* [react-app-rewire-polished](https://github.com/rawrmonstar/react-app-rewire-polished) by [@rawrmonstar](https://github.com/rawrmonstar)
* [react-app-rewire-idx](https://github.com/viktorivarsson/react-app-rewire-idx) by [@viktorivarsson](https://github.com/viktorivarsson)
* [react-app-rewire-glamorous-displayname](https://github.com/CarlRosell/react-app-rewire-glamorous-displayname) by [@CarlRosell](https://github.com/CarlRosell)
* [react-app-rewire-import](https://github.com/brianveltman/react-app-rewire-import) by [@brianveltman](https://github.com/brianveltman)
* [react-app-rewire-inline-import-graphql-ast](https://github.com/detrohutt/react-app-rewire-inline-import-graphql-ast) by [@detrohutt](https://github.com/detrohutt)
* [react-app-rewire-react-intl](https://github.com/clemencov/react-app-rewire-react-intl) by [@clemencov](https://github.com/clemencov)
* [react-app-rewire-lingui](https://github.com/Andreyco/react-app-rewire-lingui) by [@andreyco](https://github.com/Andreyco)
* [react-app-rewire-date-fns](https://github.com/stk-dmitry/react-app-rewire-date-fns) by [@stk-dmitry](https://github.com/stk-dmitry)
* [react-app-rewired-esbuild](https://github.com/fupengl/react-app-rewired-esbuild) by [@fupengl](https://github.com/fupengl)
## Webpack 插件
* [react-app-rewire-appcache-plugin](https://github.com/lwd-technology/react-app-rewire-appcache-plugin) by [@jtheis85](https://github.com/jtheis85)
* [react-app-rewire-build-dev](https://github.com/raodurgesh/react-app-rewire-build-dev) by [@raodurgesh](https://github.com/raodurgesh)
* [react-app-rewire-define-plugin](https://github.com/lwd-technology/react-app-rewire-define-plugin) by [@jtheis85](https://github.com/jtheis85)
* [react-app-rewire-favicons-plugin](https://github.com/rickycook/react-app-rewire-favicons-plugin) by [@rickycook](https://github.com/rickycook)
* [react-app-rewire-imagemin-plugin](https://github.com/lwd-technology/react-app-rewire-imagemin-plugin) by [@jtheis85](https://github.com/jtheis85)
* [react-app-rewire-modernizr](https://github.com/ctrlplusb/react-app-rewire-modernizr) by [@ctrlplusb](https://github.com/ctrlplusb)
* [react-app-rewire-preload-plugin](https://github.com/lwd-technology/react-app-rewire-preload-plugin) by [@jtheis85](https://github.com/jtheis85)
* [react-app-rewire-provide-plugin](https://github.com/lwd-technology/react-app-rewire-provide-plugin) by [@jtheis85](https://github.com/jtheis85)
* [react-app-rewire-inline-source](https://github.com/marcopeg/react-app-rewire-inline-source) by [@marcopeg](https://github.com/marcopeg)
* [react-app-rewire-webpack-bundle-analyzer](https://github.com/byzyk/react-app-rewire-webpack-bundle-analyzer) by [@byzyk](https://github.com/byzyk)
* [react-app-rewire-unplug](https://github.com/sigged/react-app-rewire-unplug) by [@sigged](https://github.com/sigged)
* [react-app-rewire-compression-plugin](https://github.com/ArVan/react-app-rewire-compression-plugin) by [@ArVan](https://github.com/ArVan)
## Loaders
* [react-app-rewire-postcss](https://github.com/csstools/react-app-rewire-postcss)
* [react-app-rewire-nearley](https://github.com/lwd-technology/react-app-rewire-nearley) by [@jtheis85](https://github.com/jtheis85)
* [react-app-rewire-coffeescript](https://github.com/stevefan1999/react-app-rewire-coffeescript) by [@stevefan1999](https://github.com/stevefan1999)
* [react-app-rewire-typescript](https://github.com/lwd-technology/react-app-rewire-typescript) by [@jtheis85](https://github.com/jtheis85)
* [react-app-rewire-typescript-babel-preset](https://github.com/strothj/react-app-rewire-typescript-babel-preset) by [@strothj](https://github.com/strothj)
* [react-app-rewire-css-modules](https://github.com/codebandits/react-app-rewire-css-modules) by [@lnhrdt](https://github.com/lnhrdt)
* [react-app-rewire-css-modules-extensionless](https://github.com/moxystudio/react-app-rewire-css-modules-extensionless) by [@moxystudio](https://github.com/moxystudio)
* [react-app-rewire-less-modules](https://github.com/andriijas/react-app-rewire-less-modules) by [@andriijas](https://github.com/andriijas)
* [react-app-rewire-stylus-modules](https://github.com/marcopeg/react-app-rewire-stylus-modules) by [@marcopeg](https://github.com/marcopeg)
* [react-app-rewire-svg-react-loader](https://github.com/codebandits/react-app-rewire-svg-react-loader) by [@lnhrdt](https://github.com/lnhrdt)
* [react-app-rewire-bem-i18n-loader](https://github.com/maxvipon/react-app-rewire-bem-i18n-loader) by [@maxvipon](https://github.com/maxvipon)
* [react-app-rewire-babel-loader](https://github.com/dashed/react-app-rewire-babel-loader) by [@dashed](https://github.com/dashed)
* [react-app-rewire-svgr](https://github.com/gitim/react-app-rewire-svgr) by [@gitim](https://github.com/gitim)
* [react-app-rewire-yaml](https://github.com/hsz/react-app-rewire-yaml) by [@hsz](https://github.com/hsz)
* [react-app-rewire-scss](https://github.com/aze3ma/react-app-rewire-scss) by [@aze3ma](https://github.com/aze3ma)
* [react-app-rewire-external-svg-loader](https://github.com/moxystudio/react-app-rewire-external-svg-loader) by [@moxystudio](https://github.com/moxystudio)
* [react-app-rewire-typings-for-css-module](https://github.com/rainx/react-app-rewire-typings-for-css-module) by [@rainx](https://github.com/rainx)
## 其他
* [react-app-rewire-create-react-library](https://github.com/osdevisnot/react-app-rewire-create-react-library) by [@osdevisnot](https://github.com/osdevisnot)
* [react-app-rewire-react-library](https://github.com/osdevisnot/react-app-rewire-contrib/tree/master/packages/react-app-rewire-react-library) by [@osdevisnot](https://github.com/osdevisnot)
* [react-app-rewire-vendor-splitting](https://github.com/andriijas/react-app-rewire-vendor-splitting) by [@andriijas](https://github.com/andriijas)
* [react-app-rewired with Inferno](packages/react-app-rewired/examples/inferno.md)
* [react-app-rewired with react-styleguideist](packages/react-app-rewired/examples/react-styleguidist.md)
* [react-app-rewired with react-hot-loader](https://github.com/cdharris/react-app-rewire-hot-loader) by [@cdharris](https://github.com/cdharris)
* [react-app-rewire-alias](https://github.com/oklas/react-app-rewire-alias) by [@oklas](https://github.com/oklas)
* [react-app-rewire-aliases](https://github.com/aze3ma/react-app-rewire-aliases) by [@aze3ma](https://github.com/aze3ma)
* [react-app-rewire-blockstack](https://github.com/harrysolovay/react-app-rewire-blockstack) by [@harrysolovay](https://github.com/harrysolovay)
* [ideal-rewires](https://github.com/harrysolovay/ideal-rewires) by [@harrysolovay](https://github.com/harrysolovay)
* [react-app-rewire-yarn-workspaces](https://github.com/viewstools/yarn-workspaces-cra-crna/tree/master/react-app-rewire-yarn-workspaces) by [@viewstools](https://github.com/viewstools)
* [react-app-rewired-single-spa](https://github.com/fupengl/react-app-rewired-single-spa) by [@fupengl](https://github.com/fupengl)
# 开发
在开发此项目时,请确保已安装 [yarn](https://yarnpkg.com/en/docs/install)
## 快速开始
要运行测试应用程序,请进入到该目录并运行:
```bash
yarn setup
yarn start
```
( 当你结束时,可以通过运行 yarn teardown 清理 )
## 命令
以下列出了可帮助您进行开发的所有可用命令
- `yarn setup` - installs dependences and links `test/react-app`
- `yarn start` - starts the react app
- `yarn build` - builds the react app
- `yarn test` - tests the react app
- `yarn teardown` - unlinks `test/react-app` and removes dependencies
# 为什么这个项目存在
参阅:[Create React App — But I don’t wanna Eject.](https://medium.com/@timarney/but-i-dont-wanna-eject-3e3da5826e39#.x81bb4kji)
================================================
FILE: bin/index.js
================================================
#!/usr/bin/env node
const { dependRequire } = require('../scripts/utils/dependRequire');
var spawn = dependRequire('react-dev-utils/crossSpawn');
const args = process.argv.slice(2);
const scriptIndex = args.findIndex(
x => x === 'build' || x === 'eject' || x === 'start' || x === 'test'
);
const script = scriptIndex === -1 ? args[0] : args[scriptIndex];
const nodeArgs = scriptIndex > 0 ? args.slice(0, scriptIndex) : [];
switch (script) {
case 'build':
case 'eject':
case 'start':
case 'test': {
const result = spawn.sync(
'node',
nodeArgs
.concat(require.resolve('../scripts/' + script))
.concat(args.slice(scriptIndex + 1)),
{ stdio: 'inherit' }
);
if (result.signal) {
if (result.signal === 'SIGKILL') {
console.log(
'The build failed because the process exited too early. ' +
'This probably means the system ran out of memory or someone called ' +
'`kill -9` on the process.'
);
} else if (result.signal === 'SIGTERM') {
console.log(
'The build failed because the process exited too early. ' +
'Someone might have called `kill` or `killall`, or the system could ' +
'be shutting down.'
);
}
process.exit(1);
}
process.exit(result.status);
break;
}
default:
console.log('Unknown script "' + script + '".');
console.log('Perhaps you need to update react-scripts?');
console.log(
'See: https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#updating-to-new-releases'
);
break;
}
================================================
FILE: bin/jest.js
================================================
#!/usr/bin/env node
/*!
* This file is necessary to allow usage of react-app-rewired as a drop-in replacement
* for react-scripts with WebStorms's test runner UI.
*
* For more information, see https://github.com/timarney/react-app-rewired/issues/182
*/
const { dependRequire } = require('../scripts/utils/dependRequire');
const spawn = dependRequire('react-dev-utils/crossSpawn');
const args = process.argv.slice(2);
// ignore --config param like it was never there
// (react-scripts adds it too and we override configuration anyway)
const configIndex = args.findIndex(x => x === '--config');
if (!!~configIndex) args.splice(configIndex, 2);
// Alternatively could be detected by presence of _INTELLIJ_JEST_CONFIG_ROOT_DIR env variable
const setupScriptFileIndex = args.findIndex(x => x === '--setupTestFrameworkScriptFile') + 1;
const isIntelliJ = !setupScriptFileIndex ? false :
args[setupScriptFileIndex].indexOf('jest-intellij-jasmine.js') !== -1;
const result = spawn.sync(
process.argv[0],
[].concat(
require.resolve('../scripts/test'),
args
), {
stdio: 'inherit',
env: Object.assign({}, process.env, isIntelliJ ? { CI: 1 } : null)
}
);
process.exit(result.signal ? 1 : result.status);
================================================
FILE: config/paths.js
================================================
module.exports = require('../overrides/paths');
================================================
FILE: config/webpack.config.js
================================================
// override paths in memory
require('../overrides/paths');
module.exports = require('../overrides/webpack');
================================================
FILE: config/webpackDevServer.config.js
================================================
// override paths in memory
require('../overrides/paths');
module.exports = require('../overrides/devServer');
================================================
FILE: config-overrides.js
================================================
const {paths} = require('./');
// load environment variables from .env files
// before overrides scripts are read
require(paths.scriptVersion + '/config/env');
const override = require(paths.configOverrides);
const webpack = typeof override === 'function'
? override
: override.webpack || ((config, env) => config);
if (override.devserver) {
console.log(
'Warning: `devserver` has been deprecated. Please use `devServer` instead as ' +
'`devserver` will not be used in the next major release.'
)
}
const devServer = override.devServer || override.devserver
|| ((configFunction) =>
(proxy, allowedHost) =>
configFunction(proxy, allowedHost));
const jest = override.jest || ((config) => config);
const pathsOverride = override.paths || ((paths, env) => paths);
// normalized overrides functions
module.exports = {
webpack,
devServer,
jest,
paths: pathsOverride
};
================================================
FILE: index.js
================================================
const paths = require('./scripts/utils/paths');
function deprecate(helper) {
throw new Error(`The "${helper}" helper has been deprecated as of v2.0. You can use customize-cra plugins in replacement - https://github.com/arackaf/customize-cra#available-plugins`);
}
module.exports = {
getLoader: function() {
return deprecate('getBabelLoader');
},
loaderNameMatches: function() {
return deprecate('loaderNameMatches');
},
getBabelLoader: function() {
return deprecate('getBabelLoader');
},
injectBabelPlugin: function() {
return deprecate('injectBabelPlugin');
},
compose: function() {
return deprecate('compose');
},
paths
};
================================================
FILE: overrides/devServer.js
================================================
const { scriptVersion } = require('../scripts/utils/paths');
const overrides = require('../config-overrides');
const devServerConfigPath = `${scriptVersion}/config/webpackDevServer.config.js`;
const devServerConfig = require(devServerConfigPath);
// override config in memory
require.cache[require.resolve(devServerConfigPath)].exports =
overrides.devServer(devServerConfig, process.env.NODE_ENV);
module.exports = require(devServerConfigPath);
================================================
FILE: overrides/jest.js
================================================
const path = require('path');
const paths = require('./paths');
const overrides = require('../config-overrides');
const rewireJestConfig = require('../scripts/utils/rewireJestConfig');
const createJestConfigPath = `${paths.scriptVersion}/scripts/utils/createJestConfig`;
// hide overrides in package.json for CRA's original createJestConfig
const packageJson = require(paths.appPackageJson);
const jestOverrides = packageJson.jest;
delete packageJson.jest;
// load original createJestConfig
const createJestConfig = require(createJestConfigPath);
// run original createJestConfig
const config = createJestConfig(
relativePath => path.resolve(paths.appPath, 'node_modules', paths.scriptVersion, relativePath),
path.resolve(paths.appSrc, '..'),
false
);
// restore overrides for rewireJestConfig
packageJson.jest = jestOverrides;
// override createJestConfig in memory
require.cache[require.resolve(createJestConfigPath)].exports =
() => overrides.jest(rewireJestConfig(config));
// Passing the --scripts-version and --config-overrides on to the original test script can result
// in the test script rejecting it as an invalid option. So strip it out of
// the command line arguments before invoking the test script.
if (paths.customScriptsIndex > -1) {
process.argv.splice(paths.customScriptsIndex, 2);
}
if (paths.configOverridesIndex > -1) {
process.argv.splice(paths.configOverridesIndex, 2);
}
module.exports = require(createJestConfigPath);
================================================
FILE: overrides/paths.js
================================================
const paths = require('../scripts/utils/paths');
const overrides = require('../config-overrides');
const pathsConfigPath = `${paths.scriptVersion}/config/paths.js`;
const pathsConfig = require(pathsConfigPath);
// extend paths with overrides
const extendedPaths = Object.assign({}, paths, overrides.paths(pathsConfig, process.env.NODE_ENV));
// override paths in memory
require.cache[require.resolve(pathsConfigPath)].exports =
extendedPaths;
module.exports = require(pathsConfigPath);
================================================
FILE: overrides/webpack.js
================================================
const semver = require('semver');
const { scriptVersion } = require('../scripts/utils/paths');
const overrides = require('../config-overrides');
const scriptPkg = require(`${scriptVersion}/package.json`);
// CRA 2.1.2 switched to using a webpack config factory
// https://github.com/facebook/create-react-app/pull/5722
// https://github.com/facebook/create-react-app/releases/tag/v2.1.2
const isWebpackFactory = semver.gte(scriptPkg && scriptPkg.version, '2.1.2');
const webpackFactoryEnvSuffix = process.env.NODE_ENV === 'production' ? '.prod' : '.dev';
const webpackConfigPath = `${scriptVersion}/config/webpack.config${!isWebpackFactory ? webpackFactoryEnvSuffix : ''}`;
const webpackConfig = require(webpackConfigPath);
// override config in memory
require.cache[require.resolve(webpackConfigPath)].exports = isWebpackFactory
? (env) => overrides.webpack(webpackConfig(env), env)
: overrides.webpack(webpackConfig, process.env.NODE_ENV);
module.exports = require(webpackConfigPath);
================================================
FILE: package.json
================================================
{
"name": "react-app-rewired",
"version": "2.2.1",
"description": "Tweak the create-react-app webpack config(s) without using 'eject' and without creating a fork of the react-scripts",
"private": false,
"bin": {
"react-app-rewired": "./bin/index.js"
},
"scripts": {
"build": "yarn --cwd 'test/react-app' build",
"clean": "rm -rf node_modules",
"setup": "yarn deps && yarn link && yarn --cwd 'test/react-app' link 'react-app-rewired'",
"start": "yarn --cwd 'test/react-app' start",
"teardown": "yarn unlink && yarn clean && yarn --cwd 'test/react-app' clean",
"test": "yarn --cwd 'test/react-app' test",
"deps": "yarn && yarn --cwd 'test/react-app'"
},
"peerDependencies": {
"react-scripts": ">=2.1.3"
},
"dependencies": {
"semver": "^5.6.0"
},
"devDependencies": {
"react-scripts": "^2.1.3"
},
"repository": {
"type": "git",
"url": "git+https://github.com/timarney/react-app-rewired"
},
"license": "MIT",
"files": [
"/index.js",
"/config-overrides.js",
"/assets",
"/bin",
"/config",
"/overrides",
"/scripts"
]
}
================================================
FILE: scripts/build.js
================================================
process.env.NODE_ENV = 'production';
const { scriptVersion } = require('./utils/paths');
// override paths in memory
require('../overrides/paths');
// override config in memory
require('../overrides/webpack');
// run original script
require(`${scriptVersion}/scripts/build`);
================================================
FILE: scripts/start.js
================================================
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
const { scriptVersion } = require('./utils/paths');
// override paths in memory
require('../overrides/paths');
// override config in memory
require('../overrides/webpack');
require('../overrides/devServer');
// run original script
require(`${scriptVersion}/scripts/start`);
================================================
FILE: scripts/test.js
================================================
process.env.NODE_ENV = process.env.NODE_ENV || 'test';
const { scriptVersion } = require('./utils/paths');
// override paths in memory
require('../overrides/paths');
// override createJestConfig in memory
require('../overrides/jest');
// run original script
require(`${scriptVersion}/scripts/test`);
================================================
FILE: scripts/utils/babelTransform.js
================================================
const { dependRequire, dependRequireResolve } = require('./dependRequire');
const babelJestMd = dependRequire('babel-jest');
const babelJest = babelJestMd.__esModule ? babelJestMd.default : babelJestMd;
const hasJsxRuntime = (() => {
if (process.env.DISABLE_NEW_JSX_TRANSFORM === 'true') {
return false;
}
try {
require.resolve('react/jsx-runtime');
return true;
} catch (e) {
return false;
}
})();
module.exports = babelJest.createTransformer({
presets: [
[
dependRequireResolve('babel-preset-react-app'),
{
runtime: hasJsxRuntime ? 'automatic' : 'classic',
},
]
],
plugins: [],
babelrc: true
});
================================================
FILE: scripts/utils/dependRequire.js
================================================
const { scriptVersion } = require('./paths');
const dependRequireResolve = (id) => require.resolve(id, { paths: [scriptVersion] });
const dependRequire = (id) => require(dependRequireResolve(id));
module.exports = {
dependRequireResolve,
dependRequire,
};
================================================
FILE: scripts/utils/paths.js
================================================
var path = require('path');
var fs = require('fs');
//try to detect if user is using a custom scripts version
var custom_scripts = process.env.REACT_SCRIPTS_VERSION || false;
const cs_index = process.argv.indexOf('--scripts-version');
if (cs_index > -1 && cs_index + 1 <= process.argv.length) {
custom_scripts = process.argv[cs_index + 1];
}
//Allow custom overrides package location
const projectDir = path.resolve(fs.realpathSync(process.cwd()));
const customPath = require(path.resolve(projectDir, 'package.json'))['config-overrides-path'];
var config_overrides = customPath
? `${ projectDir }/${ customPath }`
: `${ projectDir }/config-overrides`;
const co_index = process.argv.indexOf('--config-overrides');
var has_co_argument = false;
if (co_index > -1 && co_index + 1 <= process.argv.length) {
has_co_argument = true;
config_overrides = path.resolve(process.argv[co_index + 1]);
}
const scriptVersion = custom_scripts || 'react-scripts';
const modulePath = path.join(
require.resolve(`${scriptVersion}/package.json`),
'..'
);
const paths = require(modulePath + '/config/paths');
module.exports = Object.assign({
scriptVersion: modulePath,
configOverrides: config_overrides,
customScriptsIndex: (custom_scripts ? cs_index : -1),
configOverridesIndex: (has_co_argument ? co_index : -1),
}, paths);
================================================
FILE: scripts/utils/rewireJestConfig.js
================================================
'use strict';
const path = require('path');
const paths = require('./paths');
module.exports = (config) => {
Object.keys(config.transform).forEach((key) => {
if (config.transform[key].endsWith('babelTransform.js')) {
config.transform[key] = path.resolve(__dirname + '/babelTransform.js');
}
});
const overrides = Object.assign({}, require(paths.appPackageJson).jest);
// Jest configuration in package.json will be added to the the default config
Object.keys(overrides)
.forEach(key => {
//We don't overwrite the default config, but add to each property if not a string
if(key in config) {
if(typeof overrides[key] === 'string' || typeof overrides[key] === 'number' || typeof overrides[key] === 'boolean') {
config[key] = overrides[key];
} else if(Array.isArray(overrides[key])) {
config[key] = overrides[key].concat(config[key]);
}
else if(typeof overrides[key] === 'object') {
config[key] = Object.assign({}, config[key], overrides[key]);
}
} else {
config[key] = overrides[key];
}
});
return config;
};
================================================
FILE: test/react-app/.gitignore
================================================
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
================================================
FILE: test/react-app/README.md
================================================
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
## Available Scripts
In the project directory, you can run:
### `npm start`
Runs the app in the development mode.
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
The page will reload if you make edits.
You will also see any lint errors in the console.
### `npm test`
Launches the test runner in the interactive watch mode.
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
### `npm run build`
Builds the app for production to the `build` folder.
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.
Your app is ready to be deployed!
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
### `npm run eject`
**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
## Learn More
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
To learn React, check out the [React documentation](https://reactjs.org/).
### Code Splitting
This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
### Analyzing the Bundle Size
This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
### Making a Progressive Web App
This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
### Advanced Configuration
This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
### Deployment
This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
### `npm run build` fails to minify
This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify
================================================
FILE: test/react-app/config-overrides.js
================================================
const {
override,
} = require('customize-cra');
// override
module.exports = {
webpack: override(
// customize-cra plugins here
(config) => {
return config;
},
),
jest: config => {
return config;
},
devServer: configFunction => (proxy, allowedHost) => {
const config = configFunction(proxy, allowedHost);
return config;
},
paths: (paths, env) => {
return paths;
}
};
================================================
FILE: test/react-app/package.json
================================================
{
"name": "react-app",
"version": "0.1.0",
"private": true,
"dependencies": {
"react": "^16.7.0",
"react-dom": "^16.7.0",
"react-scripts": "2.1.3"
},
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-scripts eject",
"clean": "rm -rf node_modules"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
],
"devDependencies": {
"customize-cra": "^0.2.11"
}
}
================================================
FILE: test/react-app/public/index.html
================================================
React App
================================================
FILE: test/react-app/public/manifest.json
================================================
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
================================================
FILE: test/react-app/src/App.css
================================================
.App {
text-align: center;
}
.App-logo {
animation: App-logo-spin infinite 20s linear;
height: 40vmin;
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
================================================
FILE: test/react-app/src/App.js
================================================
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
render() {
return (
);
}
}
export default App;
================================================
FILE: test/react-app/src/App.test.js
================================================
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(, div);
ReactDOM.unmountComponentAtNode(div);
});
================================================
FILE: test/react-app/src/index.css
================================================
body {
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace;
}
================================================
FILE: test/react-app/src/index.js
================================================
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(, document.getElementById('root'));
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: http://bit.ly/CRA-PWA
serviceWorker.unregister();
================================================
FILE: test/react-app/src/serviceWorker.js
================================================
// This optional code is used to register a service worker.
// register() is not called by default.
// This lets the app load faster on subsequent visits in production, and gives
// it offline capabilities. However, it also means that developers (and users)
// will only see deployed updates on subsequent visits to a page, after all the
// existing tabs open on the page have been closed, since previously cached
// resources are updated in the background.
// To learn more about the benefits of this model and instructions on how to
// opt-in, read http://bit.ly/CRA-PWA
const isLocalhost = Boolean(
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === '[::1]' ||
// 127.0.0.1/8 is considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);
export function register(config) {
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
if (publicUrl.origin !== window.location.origin) {
// Our service worker won't work if PUBLIC_URL is on a different origin
// from what our page is served on. This might happen if a CDN is used to
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
return;
}
window.addEventListener('load', () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
if (isLocalhost) {
// This is running on localhost. Let's check if a service worker still exists or not.
checkValidServiceWorker(swUrl, config);
// Add some additional logging to localhost, pointing developers to the
// service worker/PWA documentation.
navigator.serviceWorker.ready.then(() => {
console.log(
'This web app is being served cache-first by a service ' +
'worker. To learn more, visit http://bit.ly/CRA-PWA'
);
});
} else {
// Is not localhost. Just register service worker
registerValidSW(swUrl, config);
}
});
}
}
function registerValidSW(swUrl, config) {
navigator.serviceWorker
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
if (installingWorker == null) {
return;
}
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the updated precached content has been fetched,
// but the previous service worker will still serve the older
// content until all client tabs are closed.
console.log(
'New content is available and will be used when all ' +
'tabs for this page are closed. See http://bit.ly/CRA-PWA.'
);
// Execute callback
if (config && config.onUpdate) {
config.onUpdate(registration);
}
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
console.log('Content is cached for offline use.');
// Execute callback
if (config && config.onSuccess) {
config.onSuccess(registration);
}
}
}
};
};
})
.catch(error => {
console.error('Error during service worker registration:', error);
});
}
function checkValidServiceWorker(swUrl, config) {
// Check if the service worker can be found. If it can't reload the page.
fetch(swUrl)
.then(response => {
// Ensure service worker exists, and that we really are getting a JS file.
const contentType = response.headers.get('content-type');
if (
response.status === 404 ||
(contentType != null && contentType.indexOf('javascript') === -1)
) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => {
registration.unregister().then(() => {
window.location.reload();
});
});
} else {
// Service worker found. Proceed as normal.
registerValidSW(swUrl, config);
}
})
.catch(() => {
console.log(
'No internet connection found. App is running in offline mode.'
);
});
}
export function unregister() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister();
});
}
}