2014 06 03 17 17 47 Sirolo

Monte Conero 1920x512

Monte Conero 1920x512

Setting Up Webpack For A React App

User Rating: 5 / 5

Star ActiveStar ActiveStar ActiveStar ActiveStar Active
 

Based on https://www.youtube.com/watch?v=wftux-8hqQA (Create a Modern React App From Scratch | Webpack 5 | 2021 by CyberWolve)

This setup is not a tutorial, but more of an aid-memoire to myself in setting up webpack for an application requiring react and translation. Use at your own risk.

TL;DR: Download or

git clone https://github.com/gwynsoft/webpack-react.git

 

Start by initialising a folder:

npm init -y
npm i -D @babel/core @babel/preset-env @babel/preset-react babel-loader css-loader mini-css-extract-plugin html-webpack-plugin style-loader webpack webpack-cli webpack-dev-server

style-loader injects css files directly into app bundle
mini-css-extract-plugin creates css resources separate from the app bundle

npm i react react-dom
mkdir public

Create public/index.html with:

> type ! + enter to get html skeleton:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="/main.css" class="css" />
<title>[Your Title]</title>
</head>
<body>
<div id="root"></div>

<script src="/bundle.js"></script>
</body>
</html>
mkdir src
Create src/App.js containing:
import React from "react";

const App = () => {
return <h1>Hello World</h1>;
};

export default App;

Create src/index.css containing:

h1 {
  color: red
}

Create src/index.js containing:

import React from "react";
import ReactDOM from "react-dom";

import "./index.css";
import App from "./App";

ReactDOM.render(<App />, document.getElementById("root"));

create webpack.config.js containing:

const path = require("path"); // built-in module needed to resolve paths
const HtmlWebpackPlugin = require("html-webpack-plugin"); // Generates a html file in dist with all components included

module.exports = {
output: {
path: path.resolve(__dirname, "./dist"), // Where to put the generated files
filename: "bundle.js", // Name of generated file
clean: true, // Clears the dist directory before writing new files
publicPath: "/", // for routing
},
devtool: "source-map", // Allows us to see errors with the correct file &line number
devServer: {
port: 3000,
watchFiles: ["src/*/*", "public/*/*"], // was watchContentBase
historyApiFallback: true, // **** essential for proper routing ****
open: true, // Opens a browser automatically
hot: true, // Enable hot reloading
},
module: {
rules: [
{
// Javascript and JSX files
test: /\.(js|jsx)$/,
exclude: /nodeModules/,
use: {
loader: "babel-loader",
options: { presets: [ "@babel/preset-env", ["@babel/preset-react", { runtime: "automatic" }], ], },
},
},
{
// CSS files
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
],
},
plugins: [new HtmlWebpackPlugin({ template: "./public/index.html" })],
};

In package.json add:

"scripts">
"start": "webpack serve --mode development",
"build": "webpack --mode production"

Add a favicon to /public

test with npm start

Add ESLint and Prettier Support

See How To Lint and Format Code with ESLint in Visual Studio Code (Corrected for new dependencies as at 30 Sep 21

First, add ESLint and Prettier extensions to VSCode. Then install the following dev dependencies:

npm i -D prettier eslint eslint-config-prettier @babel/eslint-parser eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-jsx-a11y eslint-plugin-import

Create .prettierrc with an empty object:

{}

Create .eslintrc with:

{
  "extends": [
    "eslint:recommended",
    "plugin:import/errors",
    "plugin:react/recommended",
    "plugin:jsx-a11y/recommended",
    "prettier"
  ],
  "rules": {
    "react/prop-types": 0,
    "no-console": 1,
    "react-hooks/rules-of-hooks": 2,
    "react-hooks/exhaustive-reps": 0,
    "no-unused-vars": 1
  },
  "plugins": ["import", "react", "jsx-a11y", "react-hooks"],
  "parserOptions": {
    "ecmaVersion": 2018,
    "sourceType": "module",
    "ecmaFeatures": {
      "jsx": true
    }
  },
  "env": {
    "es6": true,
    "browser": true,
    "node": true,
    "commonjs": true
  },
  "settings": {
    "react": {
      "version": "detect"
    }
  }
}

Add SASS functionality

npm i -D sass sass-loader

In webpack.config.js change css test to:

// CSS files
test: /\.s?css$/,
use: ["style-loader", "css-loader", "sass-loader"],

Create folder /src/styles/base, containing _global.scss, _variables.scss and _mixins.scss

Create folder /src/styles/modules

Change src/index.css to index.scss

Create _variables.scss containing:

:root {
--text: orange;
}

$bg: lightgreen;

Create styles/_global.scss containing:

@use 'variables';

body {
margin: 0;
background-color: variables.$bg; /* SASS variable */
color: var(--text); /* CSS variable */
}

Add @use './styles/base/global'; to index.scss

 

Change index.css in index.js to index.scss

Add postcss and MiniCssExtractPlugin

npm i -D postcss postcss-preset-env postcss-loader

In webpack.config.js change css use rule to:

use: [
MiniCssExtractPlugin.loader,
"css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
[
"postcss-preset-env",
{
// Options
},
],
],
},
},
},
"sass-loader",
],

The order of loaders is important!!

Add 

const MiniCssExtractPlugin = require("mini-css-extract-plugin"); after const HtmlWebpackPlugin at top of file and

'new MiniCssExtractPlugin() to plugins key then Check with npm run build

(dist/main.css should contain:
:root{--text: orange}body{margin:0;background-color:#90ee90;color:var(--text)}

/*# sourceMappingURL=main.css.map*/
)

 

Set Up Translation

npm i flag-icon-css i18next i18next-browser-languagedetector i18next-http-backend js-cookie react-i18next react-router-dom

 {jcomments on}