/cra_closer_look

An explanation of the problems that Create-React-App addresses, and how it attempts to solve them.

Primary LanguageJavaScript

Create-React-App: A Closer Look

Nitish Dayal
Last Commit Date: May 15th, 2017

About

The purpose of this document is to provide an overview of the problem/s Create-React-App attempts to solve, and how that solution is implemented. It will walk through the flow of using Create-React-App and provide insight into what each of the provided scripts do, with the intention of explaining what's happening 'behind-the-scenes' with Create-React-App. This document does not hold any information about customizing the scripts, the actual configurations for the various tools put into use by Create-React-App, or information regarding how to use those tools.

We will use the Tic-Tac-Toe project from the Intro To React tutorial as a starting point. The components have been split into separate files, and the calculateWinner function lives in the utils folder as a utility function. The source code can be found here. Feel free to clone the project and follow along.

Introduction

The Problem

As single-page applications and the needs of our users have grown in complexity, so has the landscape of front-end development. Modern single-page applications can consist of multiple JS files communicating with one another in order to manipulate the DOM, reducing (and in some cases eliminating) the need to request files from a server to update an application's UI. To allow for these JavaScript files, or modules, to interact efficiently in the browser, one option is to take advantage of a module bundler. A module bundler will parse through our code, mapping out dependencies as it comes across them, to bundle our application together in a way that the browser can understand, while still allowing developers to maintain modularity and separation in the codebase.

Some React developers write their applications using ES2015+ to utilize the benefits provided by the latest JavaScript syntax. However, browser support for changes to the JavaScript language are inconsistent at best, and we want users of our applications to have the same experience regardless of their browser choice. To ensure that our applications will run consistently and smoothly across browsers, we need to transpile our code from ES2015 down to a version of JavaScript that has better support across popular browsers.

Given that JavaScript can be fairly loose in terms of implementation it's beneficial to provide a set of rules and guidelines that application code must adhere to, as well as to provide a way to test your application against multiple scenarios and build on those tests as the application continues to grow. In order to enforce such guidelines, linters allow developers to set rules for how code should be written within the scope of their application, and will throw errors or warnings when those rules/guidelines aren't being followed. There are also many testing libraries, with variations in their approach to how an application is tested.

Implementing these tools into a project can be time consuming and overwhelming, especially if you're tasked with learning the tools while also learning a new library or framework. This creates a large 'barrier of entry' for those interested in React, but maybe lack experience working with these tools.

The Solution

Create-React-App provides a development environment with a selection of pre-configured tools to handle these needs, while providing some flexibility and customization options. Create-React-App also provides some convenience features, such as: a live development environment (intelligently updates your app in-browser as you modify your code), boilerplate code, and standard dependencies pre-installed. Developers can initiate applications via Create-React-App with confidence that the tools and configurations will allow them to take their application from development to deployment.

It also allows developers who are new to modern JavaScript tools/libraries to begin learning React without first having to decide how to set up their individual development environments and learn the necessary tools, effectively removing the barrier of entry.

Create-React-App Development Flow

Here is the directory structure of the example application found under tic-tac-toe. It is the end result of us using Create-React-App to generate the initial scaffolding, creating a folder utils/ under src/ (files necessary for the application should all be somewhere in under the src/ folder, or the public/ folder for static files).

Current Application Directory Structure:

├── node_modules/     # Installed packages necessary for Create-React-App
├── public/           # Static files
│   ├── favicon.ico
│   └── index.html
├── src/              # Application root
│   ├── components/   # Application components
│   │   ├── board.js
│   │   ├── game.js
│   │   └── square.js
│   ├── index.css
│   ├── index.js
│   ├── logo.svg
│   └── utils/        # Utility files: tools (like a custom string formatting function) to be utilized in multiple parts of the application
│       └── index.js
├── package.json
├── README.md
└── yarn.lock

4 directories, 12 files

yarn start/npm start

Webpack (the module bundler used by CRA) parses through the application starting at src/index.js, following any imported modules, until it has a complete dependency graph. In order to convert the ES2015+ code that Webpack comes across into a version of JavaScript that will behave consistently across browsers, Webpack passes any JavaScript files it comes across through Babel. Babel is a transpiler which parses newer and experimental JavaScript syntax, and transforms the code into a version of JavaScript which has better support across browsers.

Webpack uses the generated dependency graph to create a single JavaScript file consisting of the application source code and modules used by the app, injects the file via script tag into public/index.html, and starts a development server on http://localhost:3000. Navigating to this URL in the browser will show a live, interactive instance of your application. Any changes saved to the source code will reflect in the running app instance automatically.

yarn test/npm run test

Create-React-App uses the Jest testing framework to handle unit testing. Running this command will start the test runner in 'watch' mode; as you make changes to your code the tests will rerun to ensure they continue to pass. To stop this script, press Ctrl+C while your terminal is selected as the active window.

Covering the Jest framework is well outside the scope of this document, and is already quite thoroughly documented on the official website. An introduction is available in the Running Tests section of the Create-React-App documentation.

yarn build/npm run build

Create-React-App will first ensure that the files src/index.js and public/index.html exist. These files can be modified as necessary, but the names and locations shouldn't be altered. It then calls on Webpack to create an optimized, production-ready bundle of the application. Aside from actually generating a new folder & files (build/**/*), the configuration provided to Webpack for this build differs from the one used during development. Some examples of these optimizations:

  • The bundle created from this configuration has the source code minified and compressed for performance benefits.

  • The source maps generated from this configuration are full SourceMap files (*.map.js) in comparison to the less-detailed, but faster to generate SourceMap files generated from the development configuration.

For details/instructions on deploying this build, see the Create-React-App documentation under Deployment.

Post-Build Directory Structure:

├── build/
│   ├── asset-manifest.json
│   ├── favicon.ico
│   ├── index.html
│   └── static/
│       ├── css/
│       │   ├── main.09253d15.css
│       │   └── main.09253d15.css.map
│       └── js/
│           ├── main.c97b4c53.js
│           └── main.c97b4c53.js.map
├── public/
│   ├── favicon.ico
│   └── index.html
├── src/
│   ├── components/
│   │   ├── board.js
│   │   ├── game.js
│   │   └── square.js
│   ├── index.css
│   ├── index.js
│   ├── logo.svg
│   └── utils/
│       └── index.js
├── package.json
├── README.md
└── yarn.lock

8 directories, 19 files

yarn eject/npm run eject

WARNING: EJECTING IS PERMANENT. There is no 'rewind' feature.

If the needs of your application extend outside of the configuration and options provided by Create-React-App, you can eject out of Create-React-App by called yarn eject/npm run eject. Calling this command will remove the abstractions and niceties provided by Create-React-App. The configuration files, application dependencies, and NPM scripts will be exposed and available to modify as needed.

Post-Eject Directory Structure:

 # Configuration files for Jest & Webpack, and polyfills for Promises and Object.assign()
 ├── config/
 │   ├── env.js
 │   ├── jest/
 │   │   ├── cssTransform.js
 │   │   └── fileTransform.js
 │   ├── paths.js
 │   ├── polyfills.js
 │   ├── webpack.config.dev.js
 │   └── webpack.config.prod.js
 ├── node_modules/     # Installed packages necessary for Create-React-App
 ├── package.json
 ├── public/
 │   ├── favicon.ico
 │   └── index.html
 ├── scripts/          # Exposed React Scripts
 │   ├── build.js
 │   ├── start.js
 │   └── test.js
 ├── src/
 │   ├── components/
 │   │   ├── board.js
 │   │   ├── game.js
 │   │   └── square.js
 │   ├── index.css
 │   ├── index.js
 │   ├── logo.svg
 │   └── utils/
 │       └── index.js
 └── yarn.lock

8 directories, 21 files