Yet another Beginner’s Guide to setting up a React Project — Part 2

Arfat Salman
codeburst
Published in
8 min readFeb 8, 2018

--

We set up a simple React App in Part 1. We used React, React DOM and webpack-dev-server as our dependencies. We will extend the same project with other goodies that make web development easier.

Let’s begin!

JSX and React

In the last article we saw that to write <div>Hello World</div> in React, we wrote React.createElement("div", null, "Hello World"). If we want to render the following simple HTML on a page

We need to write this in React.

This looks scary! Not to mention that it is difficult to read, maintain, or understand what is going on in between all the nulls.

We, as programmers, can do better.

Facebook already realised this problem. Writing components or elements using “pure” React API was not going to work. So they created an easier-to-understand extension of React. They called it JavaScript Syntax eXtension (JSX for short). It resembles HTML syntax with few minor changes. However, JSXs are expressions of JavaScript, unlike HTML. By that I mean that you can do this: const hello = <h1>Hello</h1>. It is perfectly valid code. Under the hood, they become regular React.createElement functions. Hence, they can leverage the full power of JavaScript. You can read the full introduction here.

But now we have a problem. If you change the index.js page to include JSX, like this — you get an error.

Notice how line 5 has been changed to JSX. If we run server again, we will not get our usual output. Instead, we will get an Unexpected Token error.

The problem is that React still does not understand JSX. JSX is for our convenience and visual aid. So before you can start using JSX, you need something that can transform the JSX to a bunch of createElement functions.

Navigating through the Babel Ecosystem

The transformer that we spoke about in the last paragraph is called a transpiler. A transpiler is a program that converts the source-code of one programming language to an equivalent source-code of another programming language. In this case, it is JSX to normal React/JavaScript functions. The transpiler that we are going to use is Babel.

You know the drill by now. You need to install babel using yarn. Type yarn add -D @babel/core @babel/preset-react. We are using the latest versions of these packages. Notice that we have installed two modules: babel/core and babel/preset-react. The reasons are as follows-

Babel Core: This is heart and soul of the Babel compiler. Consider this as the engine that is going to run the transpiler. It contains the transformation logic. But the core doesn’t do anything on its own. You need to specify individual plugins for specific transformations.

Babel Plugins: The Babel core is able to carry out conversions from one language type to another. However, we still have to specify that we need to convert from JSX to normal JavaScript. For that we need to install plugins. Think of a babel plugins as a small unit of transformation. A plugin specifies

  • What source code to transform
  • What it should be transformed into
  • How to do that transformation

Now, React JSX transformations require 6 plugins, namely:

@babel/plugin-syntax-jsx
@babel/plugin-transform-react-display-name
@babel/plugin-transform-react-jsx
@babel/plugin-transform-react-jsx-self
@babel/plugin-transform-react-jsx-source

But developers of Babel thought that we, as programmers, can do better. Since a lot of people are going to use React, why not make pre-existing sets of these plugins and call it presets.

Babel presets: The presets are a collection of plugins. So, instead of installing the 6 individual plugins for React, we just installed babel/preset-react. It will install the 6 plugins for us.

To learn more about Babel, you can try the interactive editor here and see live transpilation.

So now you also have a way of using JSX in your React Apps. If you run web server again, you will still get the same Unexpected Token error. What happened now?

The Webpack Jungle

We have the transformer: Babel. We also have the transform-ee: JSX. What we need now is the program that initiates the transformation. We can do so by installing babel/cli and giving it the JS file to transform. But this would mean that every time we change the source code, we would need to run babel again.

We, as programmers, can do better. We can make this process automatic.

We are going to use webpack to achieve this. Webpack is a module bundler. It is capable of a lot of things which we will discuss in a moment. Remember that we already installed webpack in Part 1. Webpack has 4 core concepts to understand.

  • Entry: The module(s) from where to begin bundling.
  • Output: The location where to emit the bundled modules.
  • Loaders: Loaders are utilities that enable webpack to do some processing per module. Loaders can transform, or pre-process modules before the modules are bundled together.
  • Plugins: The plugins do not work per module. They extend the capabilities of webpack itself. For example- Let’s say you need to minify or compress the bundle. You can use webpack plugins to do these tasks.

Let’s talk about module bundling now.

Remember how we have installed 6 modules ( 2 dependencies + 4 devDependencies ) till now. They are React, React DOM, webpack, webpack-dev-server, babel/core, and babel/preset-env.

To render react components in the browser, the react and react-dom modules must be present while the HTML page is being evaluated. Now there are two ways to do this:

  • In the first, we put three <script /> tags. The first two contain the react and react-dom scripts. The third one will contain our components that needs to be rendered. Like this:
<script type="text/javascript" src="url/of/react.js"></script>
<script type="text/javascript" src="url/of/react-dom.js"></script>
<script type="text/javascript" src="url/of/our/components.js"></script>

But this method is not used.

  • In the other method, we can bundle react, react-dom and our components into a single file. We can name the resulting file as bundle.js and just add that one file into the script tag of our HTML page. We did this in part 1. Look at line 9 of index.html. We added bundle.js in src of script tag. This bundle.js was provided by webpack-dev-server after it did the bundling using webpack.

You may be thinking that adding 3 scripts is not that big of a deal. But imagine if your application has 20 modules or 50 modules. Also, what if those modules depend on each other. You will always need to put your script tags in such an order that the dependent is always after the thing that it is depending on. It is also called topological sorting. Doing this by hand can be very consuming and error prone.

Configuration, configurations, everywhere!

Before you can go around bundling modules, webpack needs a configuration file telling it where to begin(entry module) bundling, and where to put the output.

By default, the configuration file for webpack is called webpack.config.js. It contains an object that lists various configurations. For our purposes, we need this configuration.

A few things to note in the config object are:

  • The entry is an array that lists the modules from where to begin the bundling. It is index.js of Part 1 in our case.
  • The module key lists configuration regarding modules. It has a sub-key rules that accepts an array of rules applicable to each module.
  • The rules array comprises objects that has a few keys such as test, loaders, exclude and many more.
  • The test key is a regular expression(regex) that checks whether a module is a JS module.
  • The loaders will apply each loader in the array on the modules that passed the test.
  • In this case it is babel-loader. It will transform JSX to normal functions.
  • The exclude fields will exclude certain matching paths since they may not be part of our application such as node_modules.

In short, webpack checks each file and if the file extension is .js, webpack runs babel-loader on it, and then includes it in the bundle.

So create a webpack.config.js and paste the above configuration in it. But before you run the project, you need to install babel-loader. Type yarn add -D babel-loader@8.0.0-beta.0. We are adding an @ after babel-loader because we want a particular version of it. In this case, it is 8.0.0-beta.0.

But the struggle is not over just yet. If you type yarn start hoping to see some result on the webpage, you’ll get an error. Again. Now, what more is missing?

Let’s get things straight once again — We have a transformer: Babel. We have the transform-ee: JSX. We have an initiator and a bundler: webpack. We have configurations of webpack. What we need now are configurations of Babel. Yes! Babel also needs configurations. In Babel, we have the core and react-presets. However, we need to inform the core that we have react-presets and it needs to do transformations using these presets. Hence, a Babel configuration file.

Now, there are many ways to specify Babel configurations. One of the ways is to create a file called .babelrc. The rc is related to run command. This convention is a reminiscent of Unix style nomenclature. You can read more here.

In the .babelrc file, paste the following:

It contains one object that specifies that Babel needs to use react-presets for transformations.

Folder contents

Your folder contents should look like the folder structure in the image.

In index.js , replace line 5 with <h1>Hello World with JSX, Babel, and Webpack</h1>.

The final index.js should now look like

Updated index.js with JSX

Now, we can execute yarn start and if everything is set up correctly, you should see “Hello World with JSX, Babel and Webapck” when you navigate to http://localhost:8080/.

Lo and Behold!

This brings us to the end of part 2. We have covered a lot of ground in understanding webpack and babel. There are still many tools left to add and understand. However, this will be the final part in this two-part series.

Reach out to me @ Facebook @ Linkedin @ Twitter

--

--