Why I love Create React App
Create React App is a great React app starter and runner.
- Create React App GitHub
- Create React App User Guide
- Awesome Create React App. Feel free to file issue or suggest articles, videos and other useful resources via Pull Requests.
Before Create React App I always copy-paste webpack config and other *rc files from previous applications to each new application or even playground.
Create React App provides simple cli command to create application with the initial project structure, install dependencies and configure package.json scripts (run / build / test).
npm install -g create-react-app
create-react-app my-app
cd my-app/
npm start # yarn start
And there are no configuration. Developers can’t configure webpack, babel presets until ejection.
If you’re a power user and you aren’t happy with the default configuration, you can “eject” from the tool and use it as a boilerplate generator.
Runningnpm run eject
copies all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. Commands likenpm start
andnpm run build
will still work, but they will point to the copied scripts so you can tweak them. At this point, you’re on your own.
Why I don’t want to eject my application
This is a one-way operation. Once you eject
, you can’t go back! And I never run eject at my application because:
I want to receive create-react-app updates
For example Create React App team decided to switch to webpack 2 to support tree-shaking and a lot of other awesome features. It will be possible by just updated create-react-app version instead of updating my webpack configs.
Or Create React App team will release the Plugin System feature. I will be glad to use it and even create my own plugins. But if I had already ejected application — I will have to migrate back to Create React App.
I don’t want to see a lot of the dependencies at my package.json
Maybe this is not a problem but it is annoying me when I see all the babel*, eslint* and webpack* dependencies at package.json.
Extra configs and extra code
I always try to keep application as clean as possible. After ejection there are additional scripts and config directory . So after ejection there are ~10 new files with 50–200 lines of code at each file and in most cases only ~5 lines will be changed to add unsupported out of the box feature.
Back to the roots
After ejection and editing the configs I should copy-paste them to other applications because in most cases application’s configs (webpack loaders and plugins, babel presets) are the same.
I love Create React App because
Tool from React developers
No one can develop tool and configure bundler, code transpiler and test runner better then React developers :)
There are no configuration and no extra files at my app structure
As I wrote before — I always try to keep my application clean. So I am glad NOT to see webpack.config, scripts directory and additional dependencies at my package.json :)
Updating development stack with a single line change
Fixed development stack
Means that developers will use only stage-3 features (release candidates). Possible result of using draft features is:
Incredible fast developing tool
As the user of Create React App I am sure that I will receive all new stable features as fast as possible.
Also there are lot of interested feature requests from maintainers and community. For example:
- Plugin System
- Runtime overlay
- A global CLI for running a single component.
- Proposal: ‘configurator’ field in package.json
- Support different env configs
- and so on. and so on.
Some of them are already closed or released but I just want to show that there is a huge flow of ideas. There are even third-party tools for Create React App ecosystem like CRA generate: Scaffold a React component.
My experience using Create React App
Because of Create React App we stopped to use CSS Modules, React Toolbox and some libs that should be at webpack externals.
By the way — react-toolbox-themr providing an easy integration with Create React App
And I still don’t want to eject!
Instead of CSS Modules I started to use glamor or aphrodite. There is the similar tool — Radium, but I don’t want to use style attribute for component styling.
Loading from the global folders
I can’t work with code that require modules from parent directories:
const dateUtils = require('../../../utils/date');
Usually with webpack this is resolved by resolve.modulesDirectories configuration. As we already know — there is no webpack configuration at Create React App application but there there two solutions.
Official solution: create node_modules
at src
directory - src/node_modules as official solution for absolute imports #1065.
Another way — use NODE_PATH
env variable. It is a directory name to be resolved to the current directory as well as its ancestors, and searched for modules. More details at node official documentation "Loading from the global folders".
Use cross-env to set environment variables across platforms.
"scripts": {
"start": "cross-env NODE_PATH=src/scripts react-scripts start"
}
Or if you use .env
config - just add NODE_PATH
variable:
NODE_PATH=src/scripts
Environment configs
Create React App support .env out of the box (via dotenv). So just create .env at the root and run application. Make sure to add REACT_APP_ prefix to each variable. More info at official documentation — Adding Custom Environment Variables and Adding Development Environment Variables In .env
Multiple environment configs
Sometimes it is very useful to split configs by environments (api entry points, services keys and so on). For example my dev.env:
REACT_APP_GOOGLE_CLIENT_ID = XXX-YYY-ZZZ.apps.googleusercontent.com
REACT_APP_API_PROTOCOL = http:
REACT_APP_API_HOST = localhost:3000
NODE_PATH = src/scripts
PORT = 9001
And my prod.env:
REACT_APP_GOOGLE_CLIENT_ID = ZZZ-YYY-XXX.apps.googleusercontent.com
REACT_APP_API_PROTOCOL = https:
REACT_APP_API_HOST = api.my-applicaton.com
NODE_PATH = src/scripts
Right now it is possible by installing dotenv and updating npm scripts
:
"scripts": {
"start": "node -r dotenv/config ./node_modules/.bin/react-scripts start dotenv_config_path=dev.env",
"build": "node -r dotenv/config ./node_modules/.bin/react-scripts build dotenv_config_path=prod.env"
}
Also there is the Create React App feature request with implemented Pull Request — Support different env configs.
Read different.env
configs according to current command (start / test / build).dev.env
for start and test.prod.env
for build. If custom config does not exist — read env variables from.env
file.
So if you like this feature — provide feedback at Issue thread.
Change the dev server port
I can’t run application at 3000 port because we use Google Auth and few years ago it was configured for development at localhost:9001–9005 ports.
Add PORT
env variable. Use cross-env to set environment variables across platforms.
"scripts": {
"start": "cross-env PORT=9001 react-scripts start"
}
If you use .env
config - just add PORT
variable:
PORT=9001
Change webpack config — add plugins and change entry point
I have two situation when I have to do this:
- Add Webpack Offline Plugin.
- Publish single component as the separated build. (Seems related to How to publish components without ejecting #796)
At the first view seems that this is not possible without ejection. But there is the workaround. Anyway I don’t suggest to use this often. I am pretty sure that a lot of features are reachable with default Create React App configuration.
Always remember that using not usual loaders (like yaml, markdown, dsv loaders etc.), additional plugins and features from drafts and proposals makes your application more complex, maybe with dead syntax features and it is become impossible to migrate from current webpack configuration.
That is the reason I even do not like webpack css-loaders. I always try to require only js or json modules. From my point of view — css files are OK only at webpack entry point configuration but not for require function.
Add build:custom to npm-scripts:
"scripts": {
"build:custom": "node scripts/webpack"
}
And then create scripts/webpack.js:
const webpack = require('react-scripts/node_modules/webpack');
const craWebpackConfig = require('react-scripts/config/webpack.config.prod');
const OfflinePlugin = require('offline-plugin');
const config = {
...craWebpackConfig,
plugins: [
...craWebpackConfig.plugins,
new OfflinePlugin()
],
entry: [
craWebpackConfig.entry[0], // pollyfils
path.resolve('src', 'awesome-component.js')
],
output: {
...craWebpackConfig.output,
path: path.resolve('pf-build')
}
};
webpack(config).run(function(err, stats) {
if (err !== null) {
console.log('done');
} else {
console.log(err);
}
});
There is just webpack config extending, notreact-scripts build
. There are no beautiful console logs, comparison of the build sizes and otherreact-scripts build
command features.
There is Create React App feature request — Feature request: export scripts (start/test/build) as functions that may help to use beautiful or more correct solution.
Custom babel presets and plugins
Create React App doesn’t support decorator syntax at the moment.
There are PR Adding support for custom babel configuration #1357. If PR is merged then these features will be available:
- Decorators
- Features from stage-0 preset
- Any new babel features and presets
By default — no custom babelrc. Create it only if needed. But always remember… few paragraphs above.
![](https://i.embed.ly/1/display/resize?url=https%3A%2F%2Fpbs.twimg.com%2Fprofile_images%2F553711083064541184%2F9VsY9i09_bigger.jpeg&key=4fce0568f2ce49e8b54624ef71a8a5bd&width=40)
Despite the fact that I’m the author of Pull Request — I agree with Dan Abramov.
The end
Awesome Create React App — A collection of awesome things regarding Create React App ecosystem. Feel free to file issue or suggest articles, videos and other useful resources via Pull Requests.