React minimal setup with Webpack
In this post I’ll show a minimal Webpack setup to start working with React.
tl;dr
The final setup, with a sample component, can be found here: https://github.com/doug2k1/react-minimal-setup
What about create-react-app?
create-react-app sure is the easiest way to start developing with React, but behind those friendly scripts lies a pretty complex setup, with lots of dependencies and configurations. Sooner or later you may have to eject from it, customize or build your own setup. So it’s important to understand what each dependency and config option does. And, for me, the best way to understand it is through baby steps. So let’s do the first one.
Note: I assume you have Node.js and NPM or Yarn installed.
Dependencies
Our app dependencies are separate into two groups: dependencies, that are needed for the app execution by the end user, and dev dependencies, that are needed only during the development phase.
Before adding the dependencies we must initialize our package.json file with npm init -y
.
The only dependencies (non dev) we need are:
- react: obviously
- react-dom: to render our components on the page
npm i react react-dom
And the dev dependencies:
- webpack: will pack our JS (and possibly other file types) into one, or more, bundles
- babel-core: Babel will transform our code with JSX and ES2015 syntax to ES5, that is understandable by all browsers
- babel-loader: the loader that plugs Babel with Webpack
- babel-preset-react: Babel preset to enable JSX transformations
- babel-preset-es2015: Babel preset to enable ES2015 transformations
They are installed with --save-dev
or -D
:
npm i -D webpack babel-core babel-loader babel-preset-react babel-preset-es2015
About ES2015 (ES6)
Theoretically we could save one dependency and not use ES2015 features, but in order to create React components without it we would have to include another dependency: create-react-class. Sou we would trade one dependency with another and lose all ES2015 goodness. It’s not worth it, unless you have a very specific reason to do so.
Configuration
Webpack
Our Webpack config (webpack.config.js) is as simple as this:
const path = require('path')
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve('dist'),
filename: 'bundle.js',
},
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
},
],
},
}
It has an entrypoint (the starting point of our app execution), an output (where to save the bundled file, that will be executed by the browser) and one loader.
Our entry file uses react-dom to render our main component to the page body:
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
ReactDOM.render(<App />, document.getElementById('app'))
Babel
The Babel loader will parse all files with .js extension and convert the JSX tags and ES2015 code to valid ES5. We need to enable these two transformations on the Babel config file (.babelrc), like this:
{
"presets": [ "es2015", "react" ]
}
With this setup you can run the webpack
command to build the bundle.js file, or webpack -w
to watch for modifications and rebuild the bundle on every file change.
To actually view the result in the browser, we need an index.html file, like this:
<!DOCTYPE html>
<html>
<head>
<title>React</title>
</head>
<body>
<div id="app"></div>
<script src="dist/bundle.js"></script>
</body>
</html>
You can check the complete setup at: https://github.com/doug2k1/react-minimal-setup
See ya!