Setting up Webpack, Babel and React from scratch
Update, October 2017
I just released updated tutorial right here. So feel free to skip this one, and read a new one. It uses updated tools, and hopefully it will grow into a new series of webpack/react posts.
Update, March 2017
Webpack 2 is out, so this post is slowly becoming outdated. For webpack 2 - react boilerplate please check this post.
This is a living guide
This is the first part of the guide that will be changed over time. For now it covers Webpack, Babel (for ES6) and React with React Router.
Next parts will contain more stuff - static properties, decorators, SASS, development and production configs, immutables... Also redux part should be updated really soon.
So stay tuned!
Other parts:
- Part 1 - Webpack, Babel, React, Router, ESLint
- Part 2 - SASS, more ES6 goodness (Static props, decorators, deconstruction...)
- Part 3 - Where to go from here
Before we start
I'll assume that you have a basic knowledge of the unix terminal, and that you have read what Webpack, Babel and React are.
Webpack
For a start, install node
and npm
from https://nodejs.org/en/.
Make a git repo (this is optional, but recommended), or create an empty folder. Navigate to it in the terminal.
Initialize npm (package.json
) by running
npm init
Now we can start adding npm packages. Install babel core and it's loader for webpack.
npm install --save-dev webpack webpack-dev-server
Tip: you can use npm i
instead of npm install
.
Create app/js/app.js
with a simple console.log('hello world');
. This will be the entry point for webpack.
Now we need to create a webpack config file webpack.config.js
.
Tip: you can create files by using touch command - touch FILENAME
module.exports =;
It is important to understand what is going on so far. This tells webpack that our main application file (app.js
) is the entry point, and bundled application should be outputted to the dist
folder.
__dirname
is the name of the directory that the currently executing script resides in.
Now we can run
node ./node_modules/webpack/bin/webpack.js
It will generate dist/app.js
. (Tip: to be able to run webpack
globally, you'll need to install it using npm i --global webpack
. Then you can run it by using only webpack
.)
Babel
Noew can add Babel transpiler goodness.
Install babel core and it's loader for webpack and presets for ES6 (aka ES2015) and React
npm i --save-dev babel-loader babel-core babel-preset-es2015 babel-preset-react
Create .babelrc
in the project root folder and add presets
{
"presets": [
"es2015",
"react"
]
}
Add js/jsx loader to your webpack config, as well as extensions we want to resolve (More about this later).
...
resolve: ,
module:
...
Webpack accepts the array of the loaders. Loader has a test for the filenames, in our case it matches all of the .js
and .jsx
files. Then it applies babel loader to it. Basically this will transpile our fancy ES6 to ES5 which can be understood by browsers (some browsers can execute ES6 already, but most of them still can't).
If you re-run our webpack command, nothing will change, yet.
React
Install react and react DOM
npm i react react-dom --save
Your app.js
should look something like this. For this example we are just rendering main menu. Later we'll replace that with react router component.
;
;
;
,
'app'
;
Now we can start adding react components. Create app/js/components/Global/Menu.jsx
;
Index Page
Create index page in the app
folder.
Your app name
We'll need file loader for it
npm install file-loader --save-dev
Update webpack config to add entry
...
entry:
...
and add loader
...
...
Now when we run webpack again, we'll get index.html
and app.js
in dist folder.
Dev server and hot reload
Install webpack development server, and run it
npm install --save-dev webpack webpack-dev-server
node ./node_modules/webpack-dev-server/bin/webpack-dev-server.js
(Tip: Same as with webpack, you can install it globally npm i --global webpack-dev-server
and run it using webpack-dev-server
.)
Now open http://localhost:8080/
in your browser of choice. You should see your app. Development server will watch for your changes and rerun the bundler. Still we need to manually refresh the browser.
So let's add hot reloading.
npm install react-hot-loader --save-dev
Update webpack js/jsx loader to use hot reloading
...
...
Now we need to add two more options when running dev server --hot
and --inline
. We will also add --history-api-fallback
which will be useful when we add react router. This option tells server to fallback to index.html
which will handle routing (as we are building single page app).
node ./node_modules/webpack-dev-server/bin/webpack-dev-server.js --hot --inline
Not only the hot reload watches the changes and updates the browser, but it injects the code and keeps the application state. Note that not all modules can be replaced. The code in app/js/app.js
cannot be reloaded and will cause a full page reload but changing the children components will trigger a hot module replacement.
To make things easier, we'll add our script to the package.json
file.
...
"scripts":
...
Now we can run only npm run dev
ESLint
We are going to use AirBNB's set of rules for linting, as their standards are really good. Also, creating eslint by hand would take a long time.
Pro tip: ALWAYS LINT. No matter what people say - always use linters. You will catch errors earlier, and enforce your (the best) standards.
https://github.com/airbnb/javascript/tree/master/packages/eslint-config-airbnb
npm install --save-dev eslint eslint-config-airbnb eslint-plugin-import eslint-plugin-react eslint-plugin-jsx-a11y eslint
Now we need to create .eslintrc
that only needs extends param, but if you want to customize it, add your rules to the rules
object. Personally I like single quotes more, and spaces in the react curly synthax.
You might have to restart your editor for changes to take effect. For beginners I would recommend Atom editor.
{
"extends": "airbnb",
"rules": {
"jsx-quotes": [2, "prefer-single"],
"react/jsx-curly-spacing": [2, "always"],
"react/prefer-stateless-function": [0]
}
}
React Router
Install it from the NPM
npm install --save react-router
What we'll do is pretty much the same thing from the official getting started guide.
https://github.com/reactjs/react-router/blob/master/docs/Introduction.md
Your app.js
should look like this. You'll have to create App
, Home
and About
views.
;
;
;
;
;
;
,
'app'
;
And your views/App/index.jsx
should like this. It is just a simple wrapper around your views. It has simple menu so we can test routing. chilren
prop is every child component that is passed to it. In our case, children will be route that is matched in our app.js
.
;
;
Redux
- Note that this part will be updated soon with more details.
Install redux
npm i redux react-redux --save
To learn what redux is, the best place to start are lessons taught by the redux's creator himself, Dan Abramov.
https://egghead.io/series/getting-started-with-redux
And to add it to your React app, for now follow official documentation (more info coming soon);
http://redux.js.org/docs/basics/UsageWithReact.html
Nice to have
This is everything you need, following the best practices for react and javascipt development in general. Beside that there is couple of more things, that I usually add to my projects. Check it yourself, and add it if you thing these are useful to you.
Absolute path resolving
To be able to include your files with absolute paths you need to set root path. (Example: components/views/App
instead of ../../views/App
.) In your webpack config, under resolve add root
param. Note that you have add path
at the top of the file.
const path = require('path');
...
resolve: {
extensions: ['', '.js', '.jsx', '.json'],
root: path.resolve(__dirname, './app/js'),
},
...
Using this will probably still give you linting errors in the editor, so we need to add Install eslint import resolver package
npm install --save-dev eslint-import-resolver-webpack
And add settings to your .eslintrc
...
settings:
...
Update
As promised in comments, here you can find complete webpack.config.js
and package.json
.
To make it even easier, I created a git repository to go along with this blog post. You can find it on GitHub.
webpack.config.js
;
module.exports =
package.json
This is minimal version of the file. Yours will probably have more stuff like author
, license
...
Comments (23)