Setting Up a React.js Environment Using Npm, Babel 6 and Webpack
Facebook has really changed the way we think about front-end UI development with the introduction of React. One of the main advantages of this component based approach is, it is easy to reason about as the view is just a function of props and state.
Though the learning curve of React is shallower when compared to that of its counterparts, one intimidating aspect for the beginners is the tools (Babel, Webpack) and libraries around it.
In fact, these tools are not required to use React and but in order to get the most out of the features of ES6, JSX and bundling, we need them. In this blog post, we are going to see how to setup a React development environment without being sidetracked by the tools.
A Disclaimer: The approach that I am going to share is just for beginners to understand how to get started with React, as going by this lean way has helped a lot when I started learning React.
Let's start from scratch
Create a new folder 'react-hello-world' and initialize it with npm.
mkdir react-hello-world
cd react-hello-world
npm init
Accept the default for all the prompts
Installing and Configuring Webpack
Webpack is a module bundler which takes modules with dependencies and generates static assets by bundling them together based on some configuration.
The support of loaders in Webpack makes it a perfect fit for using it along with React and we will discuss it later in this post with more details.
Let's start with installing webpack using npm
npm i webpack -S
Webpack requires some configuration settings to carry out its work and the best practice is doing it via a config file called webpack.config.js.
touch webpack.config.js
Update the config file as follows
var webpack = require('webpack');
var path = require('path');
var BUILD_DIR = path.resolve(__dirname, 'src/client/public');
var APP_DIR = path.resolve(__dirname, 'src/client/app');
var config = {
entry: APP_DIR + '/index.jsx',
output: {
path: BUILD_DIR,
filename: 'bundle.js'
}
};
module.exports = config;
The minimalist requirement of a Webpack config file is the presence of entry and output properties.
The APP_DIR holds the directory path of the React application's codebase and the BUILD_DIR represents the directory path of the bundle file output.
As the name suggests, entry specifies the entry file using which the bundling process starts. If you are coming from C# or Java, it's similar to the class that contains main method. Webpack supports multiple entry points too. Here the index.jsx in the src/client/app directory is the starting point of the application
The output instructs Webpack what to do after the bundling process has been completed. Here, we are instructing it to use the src/client/public directory to output the bundled file with the name bundle.js
Let's create the index.jsx file in the ./src/client/app and add the following code to verify this configuration.
console.log('Hello World!');
Now in the terminal run the following command
./node_modules/.bin/webpack -d
The above command runs the webpack in the development mode and generates the bundle.js file and its associated map file bundle.js.map in the src/client/public directory.
To make it more interactive, create an index.html file in the src/client directory and modify it to use this bundle.js file
<html>
<head>
<meta charset="utf-8">
<title>React.js using NPM, Babel6 and Webpack</title>
</head>
<body>
<div id="app" />
<script src="public/bundle.js" type="text/javascript"></script>
</body>
</html>
Now if you open the browser, you can see the Hello World! in the console log.
Note: There is a webpack loader called html-loader which automatically creates this html file with the correct location of bundle.js.
Setting Up Babel-Loader
As we have seen in the beginning, by using JSX and ES6 we can be more productive while working with React. But the JSX syntax and ES6, are not supported in all the browsers.
Hence, if we are using them in the React code, we need to use a tool which translates them to the format that has been supported by the browsers. It's where babel comes into the picture.
While installing Webpack, we touched a little on loaders. Webpack uses loaders to translate the file before bundling them
To setup, install the following npm packages
npm i babel-loader babel-preset-es2015 babel-preset-react -S
The babel-preset-es2015 and babel-preset-react are plugins being used by the babel-loader to translate ES6 and JSX syntax respectively.
As we did for Webpack, babel-loader also requires some configuration. Here we need to tell it to use the ES6 and JSX plugins.
Create a .babelrc file and update it as below
touch .babelrc
{
"presets" : ["es2015", "react"]
}
The next step is telling Webpack to use the babel-loader while bundling the files
open webpack.config.js file and update it as below
// Existing Code ....
var config = {
// Existing Code ....
module : {
loaders : [
{
test : /\.jsx?/,
include : APP_DIR,
loader : 'babel'
}
]
}
}
The loaders property takes an array of loaders, here we are just using babel-loader. Each loader property should specify what are the file extension it has to process via the test property. Here we have configured it to process both .js and .jsx files using the regular expression. The include property specifies what is the directory to be used to look for these file extensions. The loader property represents the name of the loader.
Now we are done with all the setup. Let's write some code in React.
Hello React
Use npm to install react and react-dom
npm i react react-dom -S
Replace the existing console.log statement in the index.jsx with the following content
import React from 'react';
import {render} from 'react-dom';
class App extends React.Component {
render () {
return <p> Hello React!</p>;
}
}
render(<App/>, document.getElementById('app'));
Then run the following command to update the bundle file with the new changes
./node_modules/.bin/webpack -d
Now, if you open the index.html in the browser, you can see Hello React
Adding Some Complexity
Making Webpack Watch Changes
Running the webpack command every time when you change the file is not a productive workflow. We can easily change this behavior by using the following command
./node_modules/.bin/webpack -d --watch
Now Webpack is running in the watch mode, which will automatically bundle the file whenever there is a change detected. To test it, change Hello React to something else and refresh the index.html in the browser. You can see your new changes.
If you don't like refreshing the browser to see the changes, you can use react-hot-loader!
Using npm as a tool runner
The command ./node_modules/.bin/webpack can be made even simpler by leveraging npm.
Update the packages.json as below
{
// ...
"scripts": {
"dev": "webpack -d --watch",
"build" : "webpack -p"
},
// ...
}
Now the command npm run build runs Webpack in production mode, which minimizes the bundle file automatically, and
the command npm run dev runs the Webpack in the watch mode.
Adding some files
In the sample, we have seen only one Component called App. Let's add some more to test the bundling setup.
Create a new file AwesomeComponent.jsx and update it as below
import React from 'react';
class AwesomeComponent extends React.Component {
constructor(props) {
super(props);
this.state = {likesCount : 0};
this.onLike = this.onLike.bind(this);
}
onLike () {
let newLikesCount = this.state.likesCount + 1;
this.setState({likesCount: newLikesCount});
}
render() {
return (
<div>
Likes : <span>{this.state.likesCount}</span>
<div><button onClick={this.onLike}>Like Me</button></div>
</div>
);
}
}
export default AwesomeComponent;
Then include it in the index.jsx file
// ...
import AwesomeComponent from './AwesomeComponent.jsx';
// ...
class App extends React.Component {
render () {
return (
<div>
<p> Hello React!</p>
<AwesomeComponent />
</div>
);
}
}
// ...
If your Webpack is already running in watch mode, then refresh the browser to see the AwesomeComponent in action!
Summary
In this blog post, we have seen a lean approach for setting up a development environment to work with React. In the next blog post, we will be extending this example to implement the flux architecture using Alt. You can get the source code associated with this blog post can be found in my github repository.
Great tutorial! I have a better understanding on the whole process. However, there’s a minor suggestion that you need to install babel-core as well in order to making the babel-loader working!
Again, thanks for sharing!
a helpful tutorial
Thanks so much for this tutorial, really well explained!
Hey,
Is this tutorial for linux only? I had to find alternative cmd command for ‘touch’. That’s not a problem I guess but I don’t know how to run
./node_modules/.bin/webpack -dcommand on cmd.If I try it claims there no such a command and if I cd myself to .bin folder and run webpack.cmd file it can’t find the webpack.config.js file.
It says the config file must be in the .bin directory but if I place it in there it will run and create all the folders and files from there on like node_modules/.bin/src/client…
So I guess I should modify some path or something?
In case someone is as noob as I was 13 days ago. In windows you should use backslash instead of normal slash to make the command work. So correct command would be
node_modules\.bin\webpack -dI guess no-one else knew because I got no answers! x)
Hi,
Thank you for posting this tutorial.
I’m trying to learn ReactJS.
It seem it does not work anymore, it says you need to change from ‘babel’ to ‘babel-core’.
So I’ve also added the following:
npm i babel-loader babel-core babel-preset-es2015 babel-preset-react -S
Thank you very much very helpful !!!
Great guide for beginners just what I was looking for. Just a couple of things that need updating: You need to change ‘babel’ to ‘babel-loader’ in the webpack.config.js file and npm install babel-core
Hii i too beginer with react i over enjoy this article, i was run successfully, thank you
Still helping 2 years later :-) Cheers!
I think that, at least for me as a beginner, there’s a lot of things missing in the step by step tutorial for the configuration, like the folder structure. There are some steps that indicate to create files and they don’t say where to create and again, at least for me, it’s not an obvious thing
did you get it working?
Created a GitHub repository with this setup, updated for newer versions of NPM.
https://github.com/drognise…
Thanks a lot for this simple, short, straightforward, yet effective environment-oriented entry. This helped me be a good deal to get started with webpack & babel.
+1 on the ‘babel-loader’ value and on the babel-core install command (I ran into the problem as well as my version of npm is probably newer and has a breaking change).
hi, as the others suggest, pls update the webpack loader ‘babel’ to ‘babel-loader’ as it will raise an error when running the ./node_modules/.bin/webpack -d command. Good article though. Good job.
it works for me after i changed babel to babel-core.
babel-core is missing but it doesn’t cause problems, i installed it anyway.
BUT webpack -d --watch is NOT working, i refresh the page, the content does not change.
Very helpful article, had to make some changes for “win” though
linux
./node_modules/.bin/webpack -d --watch
win
node_modules.bin\webpack -d --watch
and also as they mention down there “babel-core” need to be installed to.
also creating .babelrc file
instead of
touch .babelrc
had to create file and then
ren “name”.babelrc .babelrc
but thnx for runthrough ;)
nvm…
This post is wonderful; it’s fully alleviated the apprehension I’ve felt with trying to start into webpack + React! Thanks a bunch. As others have pointed out, it’s now necessary to install babel-core as well as to include the “-loader” suffix for babel-loader in webpack.config.js.
I create https://github.com/kevalbha… for kickstart.
$ npm install -g slush-react-webpack-hmr
$ mkdir my-slush-react-webpack-hmr
$ cd my-slush-react-webpack-hmr && slush react-webpack-hmr
It will create folder structure and also install npm package and starts the webpack server with hmr
I have been struggling int that issue for 2-3 days, but your article solved all of my problems .)) thank you for your share
after babel integration by specifying webpack.config.js i run:
./node_modules/.bin/webpack -d
and get:
ERROR in Entry module not found: Error: Can’t resolve ‘babel’ in '/MYWORKDIR’
BREAKING CHANGE: It’s no longer allowed to omit the ‘-loader’ suffix when using loaders.
You need to specify ‘babel-loader’ instead of ‘babel’.
so i replaced “babel” with “babel-loader” and then it seems to work
please update the tutorial with that and the missing babel-core dep
first day on learning react. Searching to setup a simple proj. you made my day man in just quick 20min. Thank you.
Just went through this guide. It’s [99%] accurate and very practical. I am truly impressed!
Thanks! Very precise and direct…
If you can add a section about HOT and the Webserver it would be fantastic!
Also, for this simple component, you could replace the App class with:
const App = () => <p>Hello React!</p>
The less noise the better. Read [1] for more info on stateless components.
[1] https://medium.com/@joshbla…
Don’t understand why I have this error: Cannot find module "./AwesomeComponent.jsx"
https://uploads.disquscdn.c…
OK, found the problem. I forget to run: “npm run build”
Hello, I’m trying your tutorial, and I found two bugs.
In “Hello React” part, I tried : “./node_modules/.bin/webpack -d” but there are 2 errors:
1 / BREAKING CHANGE: It’s no longer allowed to omit the ‘-loader’ suffix when using loaders. You need to specify ‘babel-loader’ instead of ‘babel’.
>> So I updated webpack.config.js by changing ‘babel-loader’ instead of ‘babel’.
2 / Module build failed: Error: Cannot find module ‘babel-core’.
>> To fix this, I found this solution “npm install babel-core babel-loader --save-dev”
(I don’t understand these commands but it works lol)
Hi Tamil,
really it was a good session. very nice
This is great! got me up and running pretty quick. Would be nice to add Gulp support though.
Thank you !
am waiting for the next tutorial about implement Flux architecture using Alt !