A Webpack configuration boilerplate example with Babel, React, ESLint and more...
First we need to install webpack
and webpack-cli
as devDependencies
.
$ npm i --save-dev webpack webpack-cli
"description": "A Webpack configuration boilerplate example with Babel, React, ESLint, testing, and more...",
"scripts": {
+ "build": "webpack",
"test": "echo \"Error: no test specified\" && exit 1"
},
},
"homepage": "https://github.com/ctessier/webpack-boilerplate-example#readme",
"devDependencies": {
+ "webpack": "^5.3.2",
+ "webpack-cli": "^4.1.0"
}
}
Even though Webpack can work without any configuration file since version 4, one is necessary for this boilerplate. During the initial setup, it allows us to change the default entry and output files.
+const path = require('path');
+
+module.exports = {
+ entry: './src/App.js',
+ output: {
+ filename: 'app.js',
+ path: path.resolve(__dirname, 'dist'),
+ },
+};
Finally, we need to create our application entry file.
+console.log('Hello from App.js');
Here, we are going to install React.js.
$ npm i --save react react-dom
Because React uses ES2015 and other specific syntax, we need to transpile the code to make it compatible with most browsers. Babel helps us with that thanks to the babel-loader
. Two presets are required.
$ npm i --save-dev @babel/core babel-loader @babel/preset-env @babel/preset-react
},
"homepage": "https://github.com/ctessier/webpack-boilerplate-example#readme",
"devDependencies": {
+ "@babel/core": "^7.12.3",
+ "@babel/preset-env": "^7.12.1",
+ "@babel/preset-react": "^7.12.1",
+ "babel-loader": "^8.1.0",
"webpack": "^5.3.2",
"webpack-cli": "^4.1.0"
+ },
+ "dependencies": {
+ "react": "^17.0.1",
+ "react-dom": "^17.0.1"
}
}
Then we need to tell Webpack to use the babel-loader
on all .js
and .jsx
files.
filename: 'app.js',
path: path.resolve(__dirname, 'dist'),
},
+ module: {
+ rules: [
+ {
+ test: /\.(js|jsx)$/,
+ exclude: /node_modules/,
+ use: {
+ loader: "babel-loader",
+ },
+ },
+ ],
+ },
};
Finally, let's inform Babel to use the right presets, and we can add some React to our application!
+{
+ "presets": ["@babel/preset-env", "@babel/preset-react"]
+}
-console.log('Hello from App.js');
+import React from 'react';
+import ReactDOM from 'react-dom';
+
+ReactDOM.render(
+ <h1>Hello, world!</h1>,
+ document.getElementById('root')
+);
Here we are going to add a few plugins to the Babel configuration.
This plugin allows to add properties to our class like so:
class MyComponent extends React.Component {
- constructor(props) {
- super(props)
- this.state({ toggle: false })
- }
+ state = { toggle: false }
- toggle() {
+ toggle = () => {
this.setState(prevState => ({ toggle: !prevState.toggle }))
}
render() {
return <p>I am {this.state.toggle ? 'toggled' : 'not toggled'}</p>
}
}
We need to install the babel-plugin-proposal-class-properties plugin.
$ npm i --save-dev @babel/plugin-proposal-class-properties
{
- "presets": ["@babel/preset-env", "@babel/preset-react"]
+ "presets": ["@babel/preset-env", "@babel/preset-react"],
+ "plugins": ["@babel/plugin-proposal-class-properties"]
}
This plugin allows to import modules using absolute paths, relative to a configured path, like so:
-import Button from './components/Button';
+import Button from 'components/Button';
Let's install the plugin and configure it:
$ npm i --save-dev babel-plugin-module-resolver
{
"presets": ["@babel/preset-env", "@babel/preset-react"],
- "plugins": ["@babel/plugin-proposal-class-properties"]
+ "plugins": [
+ "@babel/plugin-proposal-class-properties",
+ ["module-resolver", {
+ "root": ["./src"]
+ }]
+ ]
}
ESLint is a linter for Javascript. It helps developers following code style rules defined for the project.
Because we use React, we need to following devDependencies
:
eslint
@babel/eslint-parser
brings Babel features for ESLint so it can analyze modern Javascripteslint-config-airbnb
provides a set of predefined ruleseslint-plugin-import
brings linting for import/export syntaxeslint-plugin-react
provides a set of predefined rules for Reacteslint-webpack-plugin
allows to run the linter while bundlingeslint-plugin-jsx-a11y
provides rules for accessibility (peer dependency of the Airbnb package)eslint-plugin-react-hooks
provides rules for React hooks (peer dependency of the Airbnb package)
$ npm i --save-dev eslint @babel/eslint-parser eslint-plugin-import eslint-config-airbnb eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-jsx-a11y
Then we need to provide ESLint with a configuration file. It is possible to run eslint --init
to automatically generate one.
+{
+ "env": {
+ "browser": true,
+ "es2021": true
+ },
+ "extends": [
+ "plugin:react/recommended",
+ "airbnb"
+ ],
+ "parser": "@babel/eslint-parser",
+ "parserOptions": {
+ "ecmaFeatures": {
+ "jsx": true
+ },
+ "ecmaVersion": 12,
+ "sourceType": "module"
+ },
+ "plugins": [
+ "react"
+ ],
+ "settings": {
+ "import/resolver": {
+ "node": {
+ "extensions": [".js"],
+ "paths": ["./src"]
+ }
+ }
+ },
+ "rules": {
+ "import/extensions": "off",
+ "react/jsx-props-no-spreading": ["warn", { "html": "ignore" }],
+ "react/state-in-constructor": ["error", "never"]
+ }
+}
Finally, to run ESLint when bundling, or via a NPM command:
mode: 'development',
entry: './src/App.jsx',
+ plugins: [
+ new ESLintPlugin({
+ files: 'src',
+ extensions: ['js', 'jsx'],
+ }),
+ ],
output: {
filename: 'app.js',
"scripts": {
"build": "webpack --mode development",
+ "lint": "eslint src --ext js,jsx",
"test": "echo \"Error: no test specified\" && exit 1"
},
- Webpack initial setup
- Babel loader for React
- Babel plugins
- ESLint check
- Html Loader and hot reloading
- Multi-outputs
- Source map files
- Multi-environment
- Mocking
- Module Replacement
- Notifier
- Bundle Analyzer
- Code-splitting
- Html Loader with multi-outputs
- cross-env
- webpack performance
maxEntrypointSize
- webpack merge
- production source maps
- transform-runtime for optimizing build size
- other plugins (see https://github.com/facebook/create-react-app/blob/master/packages/babel-preset-react-app/package.json)
- rule for ordering the imports (eslint/order)