How Create React App works

How Create React App works

So it turns out that React itself is pretty simple. It’s just a library that takes Element objects, and renders them to the DOM!

Of course, real world React apps use JSX, and JSX needs a build system. To really understand how React works, you’ll need to understand what happens before the first component is rendered. So with this in mind, let’s take a look at the four files that Create React App uses to start your app.

#src/App.js

This file exports your app’s main component.

import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

There’s nothing special about this file — you could change its name, or even remove it completely. However, React apps often follow the convention of calling their top-level component App, so Create React App is kind enough to start you off with one. We’ll go into more detail on the App component in a later lesson.

#src/index.js

This file is special — it’s your app’s entry point, and it will be run as soon as your app has loaded. By default, it’ll import the default component exported by src/App.js, and render it with ReactDOM.render().

The other interesting thing about this file is that imports serviceWorker, and then calls its unregister() method:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(<App />, 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: https://bit.ly/CRA-PWAserviceWorker.unregister();

This line and the associated serviceWorker.js file are completely safe to remove, because service workers are completely optional. In fact, while service workers can slightly speed up your app, they also can cause your app to show out-of-date content. Because of this, I’d recommend avoiding service workers at least until you’re comfortable with the basics of React itself.

#public/index.html

This is a template for the index.html file that contains your app’s root div, along with the <script> tags that load your app’s code. It’s mostly just a plain old HTML file — with a couple of differences.

  1. Interpolated constants

    This file allows you to interpolate some environment variables (but not all). In particular, it allows you to interpolate a PUBLIC_URL environment variable, which is how you can specify fully qualified URLs inside of the page <head>.

  2. Injected script tags

    Create React App will inject your app’s <script> tags at the end of this file. Of course, you can still add your own script tags too — for example, for Google Analytics or Stripe.

You won’t often need to touch this file unless you want to change the tags within your document <head>. Speaking of which, the one change you’ll often want to make in this file is the <title> tag. If you’re following along with Create React App, try this out by changing the title to something fun:

<title>Skynet</title>

#package.json

This file contains configuration for npm — the Node.js package manager. But why would you need to configure npm?

Quiz time! Do you remember how to start the development server?

$ npm run start

That’s right! To start the development server, you use npm — despite the fact that the development server is part of Create React App (and not Node.js). Huh, that’s odd. Obviously, there’s something going on here, and you may already have an idea of what it is.

#scripts

If you take a look inside package.json, you’ll find the following:

{
  "scripts": {
    "start": "react-scripts start"
  }
}

This scripts object tells npm how to respond when you call npm run <scriptname>. For example, given the above configuration, calling npm run start will cause npm to look for and execute a shell script called react-scripts, passing in start as its first argument. And if you don’t have a script called react-scripts installed globally, npm will also look in your project’s node_modules/.bin directory — which happens to contain a react-scripts file.

All of this is a bit of a mouthful, so here’s the simple version:

When calling npm run [scriptname], the corresponding script listed in package.json will be run from the node_modules/.bin directory.

So what other scripts does Create React App’s package.json include? You can find out the details in the generated README.md file, or on the Create React App website. But here’s a quick overview:

  • npm start launches the development server at localhost:3000.
  • npm test launches an interactive runner for your app’s automated tests.
  • npm run build builds a distributable version of your app, placing the result in the /build directory.
  • npm run eject basically copies-and-pastes create-react-app’s source into the current project. This allows you to modify the build system, but also significantly increases the amount of maintenance required, so you’ll want to avoid using this unless absolutely necessary.

#dependencies

After running npm init react-app, your generated package.json will list a few dependencies:

"dependencies": {
  "react": "^16.8.6",
  "react-dom": "^16.8.6",
  "react-scripts": "3.0.1"
}

You saw that last script right? It can’t be a coincidence that react-scripts is both listed as a dependency, and also available under node_modules/.bin?

So here’s how this works. When you install a dependency with npm, that dependency can ask npm to install some files into node_modules/.bin. As you may expect, the react-scripts package has asked npm to place a react-scripts file into node_modules/.bin. And that’s why it’s possible to use react-scripts within the scripts object — even though it’s not installed globally.

Of course, while dependencies can register scripts, they’re far more frequently used to package up functions and components — which your code can then import. In fact, that’s how React itself is loaded into your app:

  • The dependencies object in package.json specifies what goes in node_modules
  • The npm install command installs those packages into node_modules, and
  • import statements without a leading ./ refer to code in node_modules

If any part of this doesn’t make much sense, then that’s okay — you can always look it up in the Create React App and npm documentation if you need to. The main thing to take away right now is that these files exist, and that you can edit them if you need.

And with that out of the way? It’s time to dive into the wonderful world of state!

Progress to next section.