A Complete Webpack Setup for React
Build a React project with Webpack 4 and Babel 7
Why Webpack?
Congrats. You have started using JavaScript in your application. You have heard great things about how awesome it is. So you have a single script for your page, maybe 500 lines and it’s mostly ok to manage. As you decide to add more features, more developers join you, and the project grows.
Now the script file is big and clunky. It’s hard to maintain and to find particular sections. So, the natural decision is to split the files into several smaller files. Great! But how do you manage all of these files? And more importantly, in what order they have to be loaded! Some files depend on others to be loaded first.
You think about it for some time and decide that it would be very nice if we could add some way for a particular file to say what other files it needs to be available before it can run its?dependencies?if you will. Good news! Node.js includes a mechanism to do exactly what we want: define “modules” which can have some private/local parts, can?export?some public parts, and can?require?other modules.
Great, we now have solved the dependency problem, but we still have multiple files and the need to?bundle?it all up into a single file, and we need to make that file work in a browser (not in NodeJS).
This is why webpack exists. It’s a tool that lets you bundle your JavaScript applications (supporting both ESM and CommonJS), and it can be extended to support many different assets such as images, fonts, and stylesheets.
Webpack is a?static module bundler?for modern JavaScript applications. When webpack processes your application, it internally builds a?dependency graph?that maps every module your project needs and generates one or more?bundles.
How does it work?
First, Webpack always needs at least one?entry point, you can have multiple ones. Webpack will analyze the dependencies of this file and to another file which then, in turn, has more dependencies, so webpack can build up a dependency graph.
webpack.config.js
module.exports = {
entry: './path/to/my/entry/file.js'
};
The?output?property tells webpack where to emit the?bundles?it creates and how to name these files. It defaults to?./dist/main.js?for the main output file and to the?./dist?folder for any other generated file. And there it will put all these dependencies into that file, correctly ordered and in one concatenated
webpack.config.js
const path = require('path');
module.exports = {
entry: './path/to/my/entry/file.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-first-webpack.bundle.js'
}
};
Between the entry point and output, there are two important steps:
babel-loader and css-loader are two popular examples which get used in a lot of projects
Here we can apply some general transformations or optimizations like uglify, so this is on a global level and happens after the loaders did their job.
Finally, by setting the?mode?parameter to either?development,?production?or?none, you can enable webpack's built-in optimizations that correspond to each environment.
module.exports = {
mode: 'production'
};
So, let’s dive into building an example project setup.
Project Setup
First, you will need to download and install node
Create a folder
mkdir webpack-react-starter
cd webpack-react-starter
Init your project. -y will skip the questions
npm init -y
Install webpack, CLI and the development server for testing
npm install --save-dev webpack webpack-cli webpack-dev-server
Install React and React DOM as dependencies
npm install react react-dom
Install Core and JavasScipt Loaders
npm install --save-dev @babel/core babel-loader @babel/preset-env @babel/preset-react
Babel is a third party library that is used to convert ECMAScript 2015+ code into a backward-compatible version of JavaScript in current and older browsers or environments.
Install CSS Loaders
npm install --save-dev css-loader style-loader postcss-loader postcss --save-dev
Install Image Loaders
npm install --save-dev file-loader url-loader
领英推荐
Install Plugins
npm install --save-dev autoprefixer
npm install --save-dev html-webpack-plugin
Project Structure
Create a basic project structure:
mkdir -p src
touch src/index.html src/index.js src/index.css
Open your favourite IDE, I recommend Visual Studio code
Edit your index.html
<!DOCTYPE html
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>My React App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>>
index.html
Edit your index.js
import React from "react"
import ReactDOM from "react-dom";
import MyImage from './assets/dog.jpg';
import './index.css';
const App = () => {
return (
<div>
<div>Welcome to my-webpack-react-starter</div>
<img src={MyImage} />
</div>
);
};
ReactDOM.render(<App />, document.querySelector("#root"));;
index.js
Edit your index.css
body
margin: 50;
padding: 50;
}
div {
background-color: teal;
}
img {
width: 640px;
height: 426px;
}{
index.css
Create an?assets?folder
Add a picture of your favorite pet. I called mine dog.jpg.
This should be your project structure:
project structure
Build Configuration for Webpack and Babel
Now, we will move to the actual build configuration for babel and webpack
Create a?.babelrc?file inside the root of your project folder and insert the below lines to it.
touch .babelrc
Babel will automatically look for this file where we can configure how Babel behaves in there. In this file, you specify all the presets to apply in your code
{ "presets": ["@babel/preset-env", "@babel/preset-react"] }
In your?package.json?file include your start script for dev, your build script for the production build.
This is the complete file:
{
"name": "webpack-react-starter",
? "version": "1.0.0",
? "description": "A Webpack + Babel + React Starter bolerplate ",
? "repository": {
? ? "type": "git",
? ? "url": "https://github.com/mlomboglia/webpack-react-starter"
? },
? "keywords": [
? ? "Autoprefixer",
? ? "PostCSS",
? ? "Webpack",
? ? "React",
? ? "Babel"
? ],
? "author": "Marcos Lomboglia <[email protected]> (https://marcoslombog.com)",
? "main": "index.js",
? "scripts": {
? ? "test": "echo \"Error: no test specified\" && exit 1",
? ? "start": "webpack-dev-server --open --hot --mode development",
? ? "build": "webpack --mode production"
? },
? "license": "MIT",
? "browserslist": "> 1%,last 2 versions",
? "devDependencies": {
? ? "@babel/core": "^7.7.5",
? ? "@babel/preset-env": "^7.7.6",
? ? "@babel/preset-react": "^7.7.4",
? ? "autoprefixer": "^9.7.3",
? ? "babel-loader": "^8.0.6",
? ? "css-loader": "^3.3.2",
? ? "file-loader": "^5.0.2",
? ? "html-webpack-plugin": "^3.2.0",
? ? "postcss": "^8.1.0",
? ? "postcss-loader": "^4.0.2",
? ? "style-loader": "^1.0.1",
? ? "url-loader": "^3.0.0",
? ? "webpack": "^4.41.3",
? ? "webpack-cli": "^3.3.10",
? ? "webpack-dev-server": "^3.9.0"
? },
? "dependencies": {
? ? "react": "^16.12.0",
? ? "react-dom": "^16.12.0"
? }
}
package.json
Create a?webpack.config.js?in the root folder
const path = require('path')
const autoprefixer = require('autoprefixer');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
chunkFilename: '[id].js',
publicPath: ''
},
resolve: {
extensions: ['.js', '.jsx']
},
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.css$/,
exclude: /node_modules/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
modules: {
localIdentName: " [name]__[local]___[hash:base64:5]",
},
sourceMap: true
}
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
[ 'autoprefixer', {}, ],
],
},
}
}
]
},
{
test: /\.(png|jpe?g|gif)$/,
loader: 'url-loader?limit=10000&name=img/[name].[ext]'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: __dirname + '/src/index.html',
filename: 'index.html',
inject: 'body'
})
]
};;
webpack.config.js
Running
Let’s run our example project in development first:
npm run start
You should see a “compiled successfully” message and load the browser. If not, go to your browser on?https://localhost:8080?and you will see your running React App
To build your production release:
npm run build
You will have your production build inside the?dist?folder. Just deploy it on any static host provider like AWS S3. I will cover this in a future article.
Happy Coding.