However, getting started with a React application was so overwhelming that Dan Abramov and friends have created the create-react-app cli. Let’s see together what it does and what we can get from it.

Getting Started

First thing first, install the create-react-app npm package by running the following command:

1

2

3

npm install-gcreate-react-app

Now that we have the CLI installed globally, we can create our first React application:

1

2

3

create-react-app hello-world

After a while, you’ll get an output like the following showing a list of commands we can run:

Finally, run the application:

1

2

3

4

cdhello-world/

npm start

And that’s it ! We’ve got a nice and simple React application running. We can see it by opening our browser at http://localhost:3000/. Pretty cool, right ?!

First Look Inside

We have everything we need to start a React project without having to configure Webpack and Babel from scratch. However, I don’t know for you but I like to understand the tools I use. So, let’s have a look inside to see what we’ve got.

When we’ve launched the CLI, it has created a directory called hello-world and generated the initial project structure:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

hello-world/

├──.gitignore

├──README.md

├──favicon.ico

├──index.html

├──node_modules/

│├──react

│├──react-dom

│└──react-scripts

├──package.json

└──src

├──App.css

├──App.js

├──index.css

├──index.js

└──logo.svg

We can also note that the CLI has installed three dependencies if we look inside the node_modules directory. Plus, it has created a minimal package.json file that contains only a single build dependency and a few scripts:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

{

"name":"hello-world",

"version":"0.0.1",

"private":true,

"devDependencies":{

"react-scripts":"0.2.1"

},

"dependencies":{

"react":"^15.2.1",

"react-dom":"^15.2.1"

},

"scripts":{

"start":"react-scripts start",

"build":"react-scripts build",

"eject":"react-scripts eject"

},

"eslintConfig":{

"extends":"./node_modules/react-scripts/config/eslint.js"

}

}

The three scripts available by default allow us to:

start a local development server on localhost:3000 to run our app as we did before.

build our app for production using a dedicated Webpack config file that we’ll see in a minute.

eject to a custom setup at anytime.

At the first glance, we already feel the philosophy behind this new tool defined as follow from the Github project:

One Dependency: The package.json file is nice and clean because it contains only one build dependency even if behind the hood it uses Webpack, Babel, ESLint, and more.

Zero Configuration: The project structure contains the minimal set of required files without any configuration files. All the configuration is handled by the tool behind the scene. Hence, we don’t have to worry about it and start writing code right away.

No Lock-In: The eject command line allow us to get rid of the CLI and continue to handle our project on our own. After running this command, we’ll have the full control on our project from dependencies to configuration. This is a nice feature, but note that once we eject, we can’t go back anymore !

Start Coding with React

Okay, so before going deeper inside the tool let’s explore the React application created by default inside the src/ directory. Starting from the entry file, index.js, we note the import of react and react-dom libraries, the App component, and the stylesheet file index.css. Using react-dom, the App component is then rendered into the root element of our index.html file.

By looking at the App.js file, we can notice that it contains the App component rendering the UI we’ve seen on our browser before. It comes along with a App.css in charge of styling the React component.

Hence, this set of files constitute the start of our React project. In no time, we are ready to start coding. This is why create-react-app is so awesome !

All we need to worry about is coding our React application. Futhermore, the dev server running with the npm start command helps us a lot by displaying in the console build errors and lint warnings.

Finally, when our application is ready for production we can build an optimized bundle by running the following command:

1

2

3

npm run build

In case you feel confident and you want to get rid of this tool use the eject command:

1

2

3

npm run eject

Once again, once you run it you can’t go back. The package.json file changes from the previous one, to this:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

{

"name":"hello-world",

"version":"0.0.1",

"private":true,

"devDependencies":{

"autoprefixer":"6.3.7",

"babel-core":"6.11.4",

"babel-eslint":"6.1.2",

"babel-loader":"6.2.4",

"babel-plugin-syntax-trailing-function-commas":"6.8.0",

"babel-plugin-transform-class-properties":"6.11.5",

"babel-plugin-transform-object-rest-spread":"6.8.0",

"babel-plugin-transform-react-constant-elements":"6.9.1",

"babel-plugin-transform-runtime":"6.12.0",

"babel-preset-es2015":"6.9.0",

"babel-preset-es2016":"6.11.3",

"babel-preset-react":"6.11.1",

"babel-runtime":"6.11.6",

"case-sensitive-paths-webpack-plugin":"1.1.2",

"chalk":"1.1.3",

"cross-spawn":"4.0.0",

"css-loader":"0.23.1",

"eslint":"3.1.1",

"eslint-loader":"1.4.1",

"eslint-plugin-flowtype":"2.4.0",

"eslint-plugin-import":"1.12.0",

"eslint-plugin-jsx-a11y":"2.0.1",

"eslint-plugin-react":"5.2.2",

"extract-text-webpack-plugin":"1.0.1",

"file-loader":"0.9.0",

"filesize":"3.3.0",

"fs-extra":"0.30.0",

"gzip-size":"3.0.0",

"html-webpack-plugin":"2.22.0",

"json-loader":"0.5.4",

"opn":"4.0.2",

"postcss-loader":"0.9.1",

"promise":"7.1.1",

"rimraf":"2.5.4",

"style-loader":"0.13.1",

"url-loader":"0.5.7",

"webpack":"1.13.1",

"webpack-dev-server":"1.14.1",

"whatwg-fetch":"1.0.0"

},

"dependencies":{

"react":"^15.2.1",

"react-dom":"^15.2.1"

},

"scripts":{

"start":"node ./scripts/start.js",

"build":"node ./scripts/build.js"

},

"eslintConfig":{

"extends":"./config/eslint.js"

}

}

Our folder structure is also modified. It includes the configuration and scripts files previously handled by the CLI:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

hello-world/

├──.gitignore

├──README.md

├──config/

├──favicon.ico

├──index.html

├──node_modules/

│├──react

│├──react-dom

│└──react-scripts

├──package.json

├──scripts/

└──src

├──App.css

├──App.js

├──index.css

├──index.js

└──logo.svg

So, the configuration settings have been moved directly into our project, so we have direct control over them from now.

Deep Dive into the CLI

We’ve seen before that our project contains one build dependency called react-scripts. This is where all the magic comes from. Let’s have a look inside this black box by looking at the node_modules/react-scripts directory:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

react-scripts/

├──bin/

│└──react-scripts.js

├──config/

│├──flow/

│├──babel.dev.js

│├──babel.prod.js

│├──eslint.js

│├──paths.js

│├──polyfills.js

│├──webpack.config.dev.js

│└──webpack.config.prod.js

├──node_modules/

├──scripts/

│├──utils/

│├──build.js

│├──eject.js

│├──init.js

│└──start.js

├──template/

├──...

└──package.json

First of all, we can notice that all the configuration is located inside the config/ folder.

It contains two Webpack configuration files, one for development and one for production. Babel is used along side Webpack in order to provide React, JSX, and ES6 support. See babel.dev/prod.js:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

/**

* Copyright (c) 2015-present, Facebook, Inc.

* All rights reserved.

*

* This source code is licensed under the BSD-style license found in the

* LICENSE file in the root directory of this source tree. An additional grant

* of patent rights can be found in the PATENTS file in the same directory.

*/

module.exports={

babelrc:false,

cacheDirectory:true,

presets:[

'babel-preset-es2015',

'babel-preset-es2016',

'babel-preset-react'

].map(require.resolve),

plugins:[

'babel-plugin-syntax-trailing-function-commas',

'babel-plugin-transform-class-properties',

'babel-plugin-transform-object-rest-spread'

].map(require.resolve).concat([

[require.resolve('babel-plugin-transform-runtime'),{

helpers:false,

polyfill:false,

regenerator:true

}]

])

};

Then, by looking at the Webpack config file we know that we’ll have everything we need to start building a modern React app. Indeed, we’ve got:

A dev server with hot reloading. It also lints for common errors.

CSS and image files import directly from JavaScript.

PostCSS support to autoprefixe CSS.

A compile process to create a bundle file for our application.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

/**

* Copyright (c) 2015-present, Facebook, Inc.

* All rights reserved.

*

* This source code is licensed under the BSD-style license found in the

* LICENSE file in the root directory of this source tree. An additional grant

* of patent rights can be found in the PATENTS file in the same directory.

Finally, note that the three scripts used before are located inside the scripts/ folder. We’ll not dive into the details but we can easily understand that each JavaScript file is responsible for one particular functionnality. For instance, the build.js runs the webpack configuration to compile and create a bundle ready for production. Whereas, the start.js file starts the Webpack dev server, and the eject.js file runs the process to remove the create-react-app tool.

Conclusion

Thanks to the React team, getting started with React is becoming more easy and straightforward for beginners. All of the fundamental and universal functionnalities for building a React app are provided by the CLI. No more configuration settings to do. The configuration is abstracted from us and handled by the tool hunder the hood, unless we eject.

However, you’ll notice there are some pretty fundamental pieces that are still missing. The Github project points out the following limitations:

Server rendering.

Testing.

Some experimental syntax extensions (e.g. decorators).

CSS Modules.

LESS or Sass.

Hot reloading of components.

Overall, this project is a good starting point for those who want to learn React without struggling with all the tooling. However, I encourage you to learn Webpack and Babel that are great tools.

WELCOME

About Eloquent WebApp

EloquentWebApp is a resource for Software engineers, Web Developers and JavaScript professionals that want to invest in their skills. Time is precious, choose a lesson and start learning something right now.