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-domBecause 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-parserbrings Babel features for ESLint so it can analyze modern Javascripteslint-config-airbnbprovides a set of predefined ruleseslint-plugin-importbrings linting for import/export syntaxeslint-plugin-reactprovides a set of predefined rules for Reacteslint-webpack-pluginallows to run the linter while bundlingeslint-plugin-jsx-a11yprovides rules for accessibility (peer dependency of the Airbnb package)eslint-plugin-react-hooksprovides 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-a11yThen 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)