React with webpack - part 1

Lately I started developing using React and webpack and I just got a boost on productivity. I find this combination puts the fun back into front-end development and think you should really give it a try.

So for the sake of an example, in this series of blog posts we’ll try and build a simple property grid that is linked to a component that updates state in real time, as properties update in the property grid. You will find the complete example on github as we advance through the next posts.

This will be a series of articles on React and webpack, with multiple parts. This first part covers just the initial setup to get you going with React and displaying a hello world example (with autorefresh as you change your code)

Part 1 - initial setup

First our initial setup, create a folder for the app (let’s call it basic-property-grid), cd into it and then run

1
$ npm init

in order to initialize your app as an npm package.

Install react and webpack

Then of course you need the react npm package installed so just do

1
$ npm install --save react

After having installed react let’s install all our dev dependencies. For this we’ll need webpack and webpack-dev-server for building/developing the app. We’ll need jsx-loader in order to let webpack transform our jsx files into regular js files.

1
2
$ npm install --save-dev webpack webpack-dev-server
$ npm install --save-dev jsx-loader

Your first component

Now we are ready to write our first ReactJS component, so just create a file Hello.jsx with a basic component:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/** @jsx React.DOM */
'use strict'
var React = require('react')
module.exports = React.createClass({
displayName: 'HelloReact',
render: function(){
return <div>Hello React</div>
}
})

Now let’s create index.jsx as a starting point of our simple app.

1
2
3
4
5
6
7
8
/** @jsx React.DOM */
'use strict'
var React = require('react')
var Hello = require('./Hello')
React.renderComponent(<Hello />, document.getElementById('content'))

Configuring webpack

Then we need to pack all those files into a single bundle file, and that’s why we have chosen to use webpack. We need to create webpack.config.js which is the default file webpack will look for when launched. So here it is:

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
module.exports = {
entry: './index.jsx',
output: {
filename: 'bundle.js', //this is the default name, so you can skip it
//at this directory our bundle file will be available
//make sure port 8090 is used when launching webpack-dev-server
publicPath: 'http://localhost:8090/assets'
},
module: {
loaders: [
{
//tell webpack to use jsx-loader for all *.jsx files
test: /\.jsx$/,
loader: 'jsx-loader?insertPragma=React.DOM&harmony'
}
]
},
externals: {
//don't bundle the 'react' npm package with our bundle.js
//but get it from a global 'React' variable
'react': 'React'
},
resolve: {
extensions: ['', '.js', '.jsx']
}
}

The webpack config options are explained with comments, so you should get a basic understanding of what webpack will do given this configuration. This should be enough for now, so let’s go prepare our index.html and launch our app

index.html

We need to create an index.html file and serve it from a web server, so we install the npm http-module

1
$ npm install --save-dev http-server

index.html should look like this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html>
<head>
<title>Basic Property Grid</title>
<!-- include react -->
<script src="./node_modules/react/dist/react-with-addons.js"></script>
</head>
<body>
<div id="content">
<!-- this is where the root react component will get rendered -->
</div>
<!-- include the webpack-dev-server script so our scripts get reloaded when we make a change -->
<!-- we'll run the webpack dev server on port 8090, so make sure it is correct -->
<script src="http://localhost:8090/webpack-dev-server.js"></script>
<!-- include the bundle that contains all our scripts, produced by webpack -->
<!-- the bundle is served by the webpack-dev-server, so serve it also from localhost:8090 -->
<script type="text/javascript" src="http://localhost:8090/assets/bundle.js"></script>
</body>
</html>

Notice that index.html includes react (the version with addons) from the node_modules directory. It then includes webpack-dev-server.js script, which is a script served by the webpack-dev-server that will run on port 8090. The script is notified by the dev server whenever one of our files are changed, and reloads a new version of the bundle.
Finally we include bundle.js, served by webpack-dev-server, which contains all our files combined into one single file. NOTE: the bundle file is served from memory - no bundle.js will be created on your hard-drive at this point. This makes webpack-dev-server really fast in rebundling/reloading when changes to our codebase occur.

Prepare run scripts

The final thing is to add three scripts entries into our package.json:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"scripts": {
"start": "npm run serve | npm run dev",
"serve": "./node_modules/.bin/http-server -p 8080",
"dev": "webpack-dev-server --progress --colors --port 8090"
},
"name": "basic-property-grid",
"version": "0.1.0",
"main": "index.js",
"dependencies": {
"react": "~0.11.2"
},
"devDependencies": {
"webpack": "~1.4.4",
"webpack-dev-server": "~1.6.5",
"jsx-loader": "~0.11.2",
"http-server": "~0.7.1"
}
}

What we just did was to add 3 commands that can be run through npm run <cmd>.

  • serve - npm run serve - just starts an http-server serving files from our local dir, running on port 8080 (it serves index.html).
  • dev - npm run dev - starts webpack-dev-server on port 8090 which serves both the webpack-dev-server.js runtime and our bundle.js file.
  • start - npm run start - command simply executes serve first and then starts the dev server.

Launch

Now we are ready:

1
$ npm run start

If everything is fine, you should open localhost:8080 and have the app greet you with

Hello React

Now if you go back into your text editor, and change the text, your browser should reload automatically and reflect the changes.

All the code for this first part can be found on github/radubrehar/react-examples/basic-property-grid