Setup React with Webpack and Babel

Tags: javascript, beginners, webpack, react
Published: 2020-07-12 00:55:24

I went over setting up a basic project with Webpack in this [post], so here I'm going to just focus on how to take your React Project and upgrade it to use Webpack and Babel.

In case you forgot, Webpack will help you keep your code compartmentalized into different files, by using import and export statements and a dependency graph.

And Babel will make sure that any browser, no matter how outdated can read and understand your code!

---

Let's start off with an empty directory again and run `npm init -y` to get that package.json up and running. Then, let's install a few packages to get our demo site up and running.
```
npm install --save-dev @babel/core @babel/preset-env @babel/preset-react babel-loader
npm install --save-dev webpack webpack-cli webpack-dev-server
npm install --save react react-dom lodash
```
We need those Babel presets to parse React code. We need Webpack because that's what this whole article is about, and the Dev Server is just going to let us incorporate a live server with Webpack. We need React and React-DOM to be able to use React, and finally let's grab lodash, a library of utility functions for Javascript.

Before we can get coding let's set up a file structure.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/yfwzxv6o3wvrojo1yrbs.png "File Structure")

First let's set up the webpack.config.js file to be able to compile the jsx code.
```javascript
module.exports = {
  entry: './src/index.jsx',
  output: {
    filename: 'app.js',
    path: __dirname + 'build',
    publicPath: '/'
  },
  devServer: {
    contentBase: './build'
  },
  devtool: 'eval-source-map',
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env', '@babel/preset-react']
          }
        }
      }
    ]
  }
}
```

This should look pretty familiar. We're setting the entry and output just as before. However we've added a devServer property, which is just where the devServer is looking for files to host.

We've also added a module property. This is where we set up babel. The test just indicates that any files with those extensions should be compiled. And then we specify a loader, babel-loader, and the presets we want to use to determine how it will transform our code.

Presets load in a bunch of babel plugins automatically and are basically default environments. These two are the most basic, and will definitely get the job done, but there are lots of options out there to explore. If you want to explore individual plugins you can check the babel [docs][1], or if you want to read specifically about what each preset brings to the table, check these [docs][2].

Now set your index.html up exactly as before. It should just have a single script tag with a source of "app.js" and it should only have a div with an id of "app".

We're going to be making an App that gets some placeholder posts off the internet and displays a Post List component that displays a bunch of Posts that represent the placeholder data.

So let's start writing some React code. We'll begin with our entry point index.js.
```javascript
import ReactDOM from 'react-dom';
import React from 'react';
import App from './App.jsx';

ReactDOM.render(<App />, document.getElementById('app'));
```
We just import React, ReactDOM, and the App itself and then render it to the Dom. Easy!

Now let's kick it up a notch and look at our App.js.
```javascript
import React, { Component } from 'react';
import PostList from './PostList.jsx';

class App extends Component {
  constructor() {
    super();
    this.state = {
      posts: [],
    };
  }

   componentDidMount () {
    fetch('https://jsonplaceholder.typicode.com/posts')
      .then(res => {
        res.json()
          .then(posts => {
            this.setState({posts});
          });
      });
  }

  render () {
    return (
      <div>
        <PostList posts={this.state.posts} />
      </div>
    );
  }
}

export default App;
```
You can see we import React and Component here as well as our next piece of the puzzle, a PostList. Which we call with a list of posts.

We get all our posts from a database of dummy data in our componentDidMount, don't worry about the mechanics of that, let's just focus on hooking all these parts together.

So let's look at our PostList.jsx next. We're going to import lodash here as well, just to see how it's done, but you could easily just use the built in map.

Since we only want map we destructure the object we're importing from lodash and only save the map function out of it. Than we can just call `map` instead of `_.map`.
```javascript
import React from 'react';
import { map } from 'lodash';
import Post from './Post.jsx';

const postList = ({posts}) => (
  <div>
    {map(posts, post => <Post key={post.id} post={post} />)}
  </div>
);

export default postList;
```
Let's follow our chain down to the bottom, Post.jsx. Here we only have to import React and export the post.
```javascript
import React from 'react';

const post = ({post: {title, body}}) => {
  return (
    <div>
      <p>{title}</p>
      <p>{body}</p>
    </div >
  );
}

export default post;
```
Alright! We got all of our example React code up! Now let's add a script to start our dev server so we can just make changes to the files and get updates to our locally hosted site live. So add a script to your package.json file.
```javascript
"start": "webpack-dev-server --config ./webpack.config.js"
```
So now when you run `npm start` in the terminal, you'll have an easy to debug, live updating, local server showing your brand new App!

---
Once again, this is a very simple app, but hopefully this will help you to see how using import and export statements can be scaled up to larger applications. And learning how to make a compiler work with a bundler is going to be very helpful knowledge to have.

[post]: https://dev.to/dtroyano86/how-to-setup-a-javascript-project-with-webpack-259a
[1]: https://babeljs.io/docs/en/plugins
[2]: https://babeljs.io/docs/en/presets