How to setup a React Environment using Webpack and Babel

How to setup a React Environment using Webpack and Babel

In this article, you'll learn setup a React Environment using Webpack and Babel

React is a Javascript library, by Facebook, that is used for building user interfaces. It is a bomb library that offers so many advantages but one of the biggest setbacks is the steep learning curve. When I started out, one of the things that bugged me a whole lot was that most of the tutorials skipped over the React environment set-up.

So here we go, this article is best suited for beginners who aren't afraid to get their hands dirty setting up a React environment, from scratch. My number one mission is to keep this article simple and easy to understand. I will not use any boilerplates and you can find the whole set-up on my github repo here. We will be using the following:

Table of Contents

  • Pre-requisites
  • Getting Started
  • Webpack installation and configuration
  • Setting up Babel
  • Setting up our React Components
  • Html-Webpack-Plugin
  • Run it!
  • React, React, React
  • Conclusion
  1. Webpack - A module bundler
  2. Babel - A Javascript compiler
  3. ES6 - A relatively new Javasript standard
  4. Yarn - A package manager
  5. React - As expected

This article is best suited for beginners who aren't afraid to get their hands dirty setting up a React environment from scratch.

By the end of the tutorial, we will have set-up a working React environment and just for fun we will have a simple webpage displaying Hello World.

Brace yourselves for some fun!!

Pre-requisites

We require Yarn and Node pre-installed on our machines before we dive into the project.

As mentioned above we'll use Yarn Package Manager. It is quite similar to npm and has almost the same commands provided by npm. It also comes with a few extra features that npm does not provide. Just to catch you up, a few of the main reasons I use yarn are:

  • If you had already installed a package before, you can install it again without any internet connection. Apart from the fact that you can install packages offline, this also increases the speed of your installments.
  • The same exact dependencies are installed on any machine. This essentially means that an install on one machine will work the same exact way on any other machine.

For more information you could go over the Yarn documentation.

For Mac Os users, the commands below will suffice to install Yarn and because I got all your backs, anyone using any other OS can head on over to the Yarn installation page to get the right instructions on installation.

> brew update
> brew install yarn
Getting Started

Open your terminal and create a new folder. You can name it as you wish. Navigate into the folder and initialize the project by running yarn init. yarn init just like npm init will give you a few prompts, just press enter till the end or configure it as you'd like to.

> mkdir hello-world-react
> cd hello-world-react
> yarn init

When yarn init is finished you will notice in your folder, in this case 'hello-world-react', you'll have a new file package.json just like if you had done npm init.

Webpack installation and configuration

Next, we need to install webpack and a few dependencies.

> yarn add webpack webpack-dev-server path

Inside 'hello-world-react' a new file yarn.lock is created. This file is what Yarn uses to lock down the exact dependencies to use on another machine, you don't really have to worry about this file as it is automatically generated.

Now that we have webpack installed we need a config file to give it instructions on what to do. Create a new file, webpack.config.js, on the project folder and open it on your preferred text editor.

> touch webpack.config.js

We can then update the configuration file:

/*
    ./webpack.config.js
*/
const path = require('path');
module.exports = {
  entry: './client/index.js',
  output: {
    path: path.resolve('dist'),
    filename: 'index_bundle.js'
  },
  module: {
    rules: [
      { test: /\.css$/,
        use: [
          { loader: "style-loader" },
          { loader: "css-loader" }
        ]
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: "babel-loader"
      }, {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        use: "babel-loader"
      }
    ]
  }
}

Basically, to get a running instance of webpack we need to specify an entry point and an output.

  • entry: Specifies the entry file where the bundler starts the bundling process.
  • output: Specifies the location where the bundled Javascript code is to be saved.

We, however, also have loaders. These are needed because we want the browser we use to be able to interprate and run JSX code (for React) and code written in ES6.

  • loaders: They are transformations that are applied on a file in our app.

The loaders key property takes in an array of loaders. For our basic set-up we specified that the babel-loader goes through and transpiles every file that ends with a .js or .jsx extension excluding the files inside the node_modules folder. You could always add more loaders as needed. For example, if you had separate style sheets in your project you'd require a CSS loader. All these loaders can be found in the webpack documentation. Feel free to test them out.

Setting up Babel

In our webpack configuration, we specified that we are using a babel-loader. Where does this babel-loader come from you ask? Well, we need to install it and later set a few configurations.

> yarn add babel-loader babel-core babel-preset-es2015 babel-preset-react --dev

Those are all the dependencies we need for Babel. Notice we have installed babel-preset-es2015 and babel-preset-react, presets are Babel plugins that simply tell Babel what to look out for and transform into plain, vanilla Javascript.

We then have to configure Babel and we can do this in a new file which we'll name .babelrc.

> touch .babelrc

Then we can update the file to:

/* 
    ./.babelrc
*/    
{
    "presets":[
        "es2015", "react"
    ]
}

That is it. Now when babel-loader is called in the webpack config file it knows what to do.

Setting up our React Components

So far our file structure looks like this:

.
|-- node_modules
|-- .babelrc
|-- package.json
|-- webpack.config.js
|-- yarn.lock

Its high time we add the React side don't you think? We'll create a new folder client and add an index.js file and an index.html file.

> mkdir client
> cd client
> touch index.js
> touch index.html
> cd .. 

Now we have this:

.
|-- client
     |-- index.html
     |-- index.js
|-- .babelrc
|-- package.json
|-- webpack.config.js
|-- yarn.lock

Next we need to add some code. We'll start out with something simple just to verify that our set-up so far works.

Open up index.js and add:

/*
    ./client/index.js
    which is the webpack entry file
*/
console.log('Hey guys and ladies!!')

Update index.html to:

/*
    ./client/index.html
    basic html skeleton
*/


  
    
    React App Setup
  
  
    

    
  


The index.html is the actual webpage which loads our React Components on the browser. I mentioned before that we need babel in order to compile our code into a syntax that browsers support. We code our React components using JSX and in our case we will also use ES6. The syntax of these two modules is not supported by most browsers therefore, we have to run this code through the babel loaders and then the bundled output is what we'll specify to be displayed on index.html.

One way to add the bundled file to our HTML is to insert a script tag and pass the location of the bundled file into the script tag. A better way to do this is to use this nifty package called html-webpack-plugin. It provides an easy way to have all your HTML generated for you. All you need is the standard HTML skeleton and it'll take care of your script insertions with just a few configurations. Let's do that next.

Html-Webpack-Plugin

First, we'll install the plugin. Make sure your terminal is currently reading you're root project folder, hello-world-react, then enter the following command:

> yarn add html-webpack-plugin

Then open up your webpack.config.js and add a few configurations.

/* 
    ./webpack.config.js
*/
const path = require('path');

const HtmlWebpackPlugin = require('html-webpack-plugin');
const HtmlWebpackPluginConfig = new HtmlWebpackPlugin({
  template: './client/index.html',
  filename: 'index.html',
  inject: 'body'
})

module.exports = {

...

module: {
    rules: [
        ...
    ]
},
// add this line
plugins: [HtmlWebpackPluginConfig]
}

The configuration is pretty self-explanatory. We require the html-webpack-plugin and then create a new instance of it, and set our skeleton HTML as the template. filename refers to the name of the HTML that the plugin will generate. inject body tells the plugin to add any JavaScript into the bottom of the page, just before the closing body tag.

Run it!

We are almost at the finish line. Let's try run our setup. We just need to do one tiny thing first. Open up your package.json and let's add a start script.

/*
    ./package.json
*/
{
  "name": "hello-world-react",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",

  // add the scripts key to your package.json

  "scripts": {
    "start": "webpack-dev-server"
  },

  "dependencies": {
  ...
  },
  "devDependencies": {
  ...
  }
}

Now we can go to our terminal and run:

> yarn start

Open your browser on [http://localhost:8080/](http://localhost:8080/). If you check your console you'll see our message "Hey guys and ladies!!". The reason we use localhost:8080 is because webpack-dev-server serves all our files on port 8080. Notice webpack-dev-server is run when we execute our start script.

Yay, it works. So let's add a simple React Component and see what happens.

React, React, React

I'll do a very basic Hello World React Component. We need to install React dependencies first.

> yarn add react react-dom

Next in the client folder we can add a folder named components and create a file App.jsx.

> cd client
> mkdir components 
> cd components
> touch App.jsx
> cd ../..

So our file structure now looks like this:

.
|-- client
     |-- components
         |-- App.jsx
     |-- index.html
     |-- index.js
|-- .babelrc
|-- package.json
|-- webpack.config.js
|-- yarn.lock

While naming component files in React the convention is to use PascalCase thats why our file name starts with a capitalized letter.The extension could be either .jsx or .js, I find it better to explicitly use the .jsx extention on files that I intend to use JSX syntax.

Next let's update the App.jsx file:

/*
    ./client/components/App.jsx
*/
import React from 'react';

export default class App extends React.Component {
  render() {
    return (
     
        # Hello World

      );
  }
}

Lastly, we render our component from our start file, index.js. Let's replace the console.log() with:

/* 
    ./client/index.js
*/
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App.jsx';

ReactDOM.render(, document.getElementById('root'));

Open bash and start our project. Make sure your terminal reads that you are on the project root folder.

> yarn start

There we go! Ecstatic that you got all the way to the end!!

Conclusion

We now have a working React Environment set-up. I hope that this tutorial shed some light on what the configurations really do and why we need them. Also, if the set-up is a bit too tasking to do on every project you can always fork my repo and have a base to start from.

Please feel free to experiment around with different webpack configurations and hit me up with any cool things you've discovered on the comment section.

Finally, you can and should try build up a more in depth React Project after the tutorial.

JavaScript developers should you be using Web Workers?

JavaScript developers should you be using Web Workers?

Do you think JavaScript developers should be making more use of Web Workers to shift execution off of the main thread?

Originally published by David Gilbertson at https://medium.com

So, Web Workers. Those wonderful little critters that allow us to execute JavaScript off the main thread.

Also known as “no, you’re thinking of Service Workers”.

Photo by Caleb Jones on Unsplash

Before I get into the meat of the article, please sit for a lesson in how computers work:

Understood? Good.

For the red/green colourblind, let me explain. While a CPU is doing one thing, it can’t be doing another thing, which means you can’t sort a big array while a user scrolls the screen.

This is bad, if you have a big array and users with fingers.

Enter, Web Workers. These split open the atomic concept of a ‘CPU’ and allow us to think in terms of threads. We can use one thread to handle user-facing work like touch events and rendering the UI, and different threads to carry out all other work.

Check that out, the main thread is green the whole way through, ready to receive and respond to the gentle caress of a user.

You’re excited (I can tell), if we only have UI code on the main thread and all other code can go in a worker, things are going to be amazing (said the way Oprah would say it).

But cool your jets for just a moment, because websites are mostly about the UI — it’s why we have screens. And a lot of a user’s interactions with your site will be tapping on the screen, waiting for a response, reading, tapping, looking, reading, and so on.

So we can’t just say “here’s some JS that takes 20ms to run, chuck it on a thread”, we must think about where that execution time exists in the user’s world of tap, read, look, read, tap…

I like to boil this down to one specific question:

Is the user waiting anyway?

Imagine we have created some sort of git-repository-hosting website that shows all sorts of things about a repository. We have a cool feature called ‘issues’. A user can even click an ‘issues’ tab in our website to see a list of all issues relating to the repository. Groundbreaking!

When our users click this issues tab, the site is going to fetch the issue data, process it in some way — perhaps sort, or format dates, or work out which icon to show — then render the UI.

Inside the user’s computer, that’ll look exactly like this.

Look at that processing stage, locking up the main thread even though it has nothing to do with the UI! That’s terrible, in theory.

But think about what the human is actually doing at this point. They’re waiting for the common trio of network/process/render; just sittin’ around with less to do than the Bolivian Navy.

Because we care about our users, we show a loading indicator to let them know we’ve received their request and are working on it — putting the human in a ‘waiting’ state. Let’s add that to the diagram.

Now that we have a human in the picture, we can mix in a Web Worker and think about the impact it will have on their life:

Hmmm.

First thing to note is that we’re not doing anything in parallel. We need the data from the network before we process it, and we need to process the data before we can render the UI. The elapsed time doesn’t change.

(BTW, the time involved in moving data to a Web Worker and back is negligible: 1ms per 100 KB is a decent rule of thumb.)

So we can move work off the main thread and have a page that is responsive during that time, but to what end? If our user is sitting there looking at a spinner for 600ms, have we enriched their experience by having a responsive screen for the middle third?

No.

I’ve fudged these diagrams a little bit to make them the gorgeous specimens of graphic design that they are, but they’re not really to scale.

When responding to a user request, you’ll find that the network and DOM-manipulating part of any given task take much, much longer than the pure-JS data processing part.

I saw an article recently making the case that updating a Redux store was a good candidate for Web Workers because it’s not UI work (and non-UI work doesn’t belong on the main thread).

Chucking the data processing over to a worker thread sounds sensible, but the idea struck me as a little, umm, academic.

First, let’s split instances of ‘updating a store’ into two categories:

  1. Updating a store in response to a user interaction, then updating the UI in response to the data change
  2. Not that first one

If the first scenario, a user taps a button on the screen — perhaps to change the sort order of a list. The store updates, and this results in a re-rendering of the DOM (since that’s the point of a store).

Let me just delete one thing from the previous diagram:

In my experience, it is rare that the store-updating step goes beyond a few dozen milliseconds, and is generally followed by ten times that in DOM updating, layout, and paint. If I’ve got a site that’s taking longer than this, I’d be asking questions about why I have so much data in the browser and so much DOM, rather than on which thread I should do my processing.

So the question we’re faced with is the same one from above: the user tapped something on the screen, we’re going to work on that request for hopefully less than a second, why would we want to make the screen responsive during that time?

OK what about the second scenario, where a store update isn’t in response to a user interaction? Performing an auto-save, for example — there’s nothing more annoying than an app becoming unresponsive doing something you didn’t ask it to do.

Actually there’s heaps of things more annoying than that. Teens, for example.

Anyhoo, if you’re doing an auto-save and taking 100ms to process data client-side before sending it off to a server, then you should absolutely use a Web Worker.

In fact, any ‘background’ task that the user hasn’t asked for, or isn’t waiting for, is a good candidate for moving to a Web Worker.

The matter of value

Complexity is expensive, and implementing Web Workers ain’t cheap.

If you’re using a bundler — and you are — you’ll have a lot of reading to do, and probably npm packages to install. If you’ve got a create-react-app app, prepare to eject (and put aside two days twice a year to update 30 different packages when the next version of Babel/Redux/React/ESLint comes out).

Also, if you want to share anything fancier than plain data between a worker and the main thread you’ve got some more reading to do (comlink is your friend).

What I’m getting at is this: if the benefit is real, but minimal, then you’ve gotta ask if there’s something else you could spend a day or two on with a greater benefit to your users.

This thinking is true of everything, of course, but I’ve found that Web Workers have a particularly poor benefit-to-effort ratio.

Hey David, why you hate Web Workers so bad?

Good question.

This is a doweling jig:

I own a doweling jig. I love my doweling jig. If I need to drill a hole into the end of a piece of wood and ensure that it’s perfectly perpendicular to the surface, I use my doweling jig.

But I don’t use it to eat breakfast. For that I use a spoon.

Four years ago I was working on some fancy animations. They looked slick on a fast device, but janky on a slow one. So I wrote fireball-js, which executes a rudimentary performance benchmark on the user’s device and returns a score, allowing me to run my animations only on devices that would render them smoothly.

Where’s the best spot to run some CPU intensive code that the user didn’t request? On a different thread, of course. A Web Worker was the correct tool for the job.

Fast forward to 2019 and you’ll find me writing a routing algorithm for a mapping application. This requires parsing a big fat GeoJSON map into a collection of nodes and edges, to be used when a user asks for directions. The processing isn’t in response to a user request and the user isn’t waiting on it. And so, a Web Worker is the correct tool for the job.

It was only when doing this that it dawned on me: in the intervening quartet of years, I have seen exactly zero other instances where Web Workers would have improved the user experience.

Contrast this with a recent resurgence in Web Worker wonderment, and combine that contrast with the fact that I couldn’t think of anything else to write about, then concatenate that combined contrast with my contrarian character and you’ve got yourself a blog post telling you that maybe Web Workers are a teeny-tiny bit overhyped.

Thanks for reading

If you liked this post, share it with all of your programming buddies!

Follow us on Facebook | Twitter

Further reading

An Introduction to Web Workers

JavaScript Web Workers: A Beginner’s Guide

Using Web Workers to Real-time Processing

How to use Web Workers in Angular app

Using Web Workers with Angular CLI