How To Setup a Webpack For React Js

In this article, we will learn how to setup a webpack in our application.

Webpack also referred to as module bundler, is a tool for compiling JavaScript modules. It turns a large number of files into a single file (or a few files) that runs your software. It is capable of a wide range of jobs, including supporting you in putting your resources together.

Frist run the following command and create a project,

$ npx create-react-app webpack-configs
$ cd webpack-configs

Now install webpack and babel,

npm i -D webpack webpack-cli webpack-dev-server html-webpack-plugin @babel/core @babel/preset-env babel-loader @babel/preset-react babel-plugin-transform-class-properties babel-plugin-transform-es2015-modules-commonjs

Once done, add your package.json file in following script,

  "scripts": {
    ...
    "webpack": "webpack",
    "webpack-dev-server": "webpack-dev-server",
    "dev": "npm run webpack-dev-server -- --env mode=development",
    "prod": "npm run webpack -- --env mode=production"
}

Then for the configuration of the babel you have to add the following command,

$ touch .babelrc

And add the following code into babelrc file

{
    "presets": [
        "@babel/preset-react",
        [
            "@babel/preset-env",
            {
                "targets": {
                    "browsers": "last 2 versions"
                },
                "modules": false,
                "loose": false
            }
        ]
    ],
    "plugins": [
        "transform-class-properties"
    ],
    "env": {
        "test": {
            "plugins": [
                "transform-es2015-modules-commonjs"
            ]
        }
    }
}

We’ll also need a file to store our app’s generic webpack configurations. Run the following command in your terminal:

$ touch webpack.config.js

Add following command to configrating webpack to load and static files

$ npm i -D babel-loader file-loader url-loader

Add following code into webpack file

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = ({ mode } = { mode: "production" }) => {
    console.log(`mode is: ${mode}`);

    return {
            mode,
            entry: "./src/index.js",
            output: {
                publicPath: "/",
                path: path.resolve(__dirname, "build"),
                filename: "bundle.js"
            },
            module: {
                rules: [
                 {
                    test: /\.jpe?g|png$/,
                    exclude: /node_modules/,
                    use: ["url-loader", "file-loader"]
                },
                    {
                        test: /\.(js|jsx)$/,
                        exclude: /node_modules/,
                        loader: "babel-loader"
                    }
                ]
            },
            plugins: [
                new HtmlWebpackPlugin({
                    template: "./public/index.html"
                }),
            ]
        }
};

Then you should on devserver in webpack file

devServer: {
  open: true
}

Then we have to setting hot modules replacement

However, we do have a problem. The server reloads every time we make a modification, and we lose our state. To address this, we may use the Hot Module Replacement plugin that comes with webpack in our setup. Make the following changes to the webpack.config.js file:

const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = ({ mode } = { mode: "production" }) => {
    console.log(`mode is: ${mode}`);

    return {
            mode,
            entry: "./src/index.js",
            devServer: {
                hot: true,
                open: true
            },
            output: {
                publicPath: "/",
                path: path.resolve(__dirname, "build"),
                filename: "bundle.js"
            },
            module: {
                rules: [
                    {
                        test: /\.(js|jsx)$/,
                        exclude: /node_modules/,
                        loader: "babel-loader"
                    }
                ]
            },
            plugins: [
                new HtmlWebpackPlugin({
                    template: "./public/index.html"
                }),
                new webpack.HotModuleReplacementPlugin()
            ]
        }

};

Then add following command

npm i -D react-hot-loader

Update babelrc file

{
  "presets": [
    "@babel/preset-react",
    [
     "@babel/preset-env",
      {
        "targets": {
          "browsers": "last 2 versions"
        },
        "modules": false,
        "loose": false
      }
    ]
  ],
  "plugins": [
    "transform-class-properties", "react-hot-loader/babel"
  ],
  "env": {
    "test": {
      "plugins": [
        "transform-es2015-modules-commonjs"
      ]
   }
  }
}

Add below code in your index.js file

    
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import reportWebVitals from './reportWebVitals';

const rootId = document.getElementById("root");

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  rootId
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
if (module.hot && process.env.NODE_ENV === "development") {
  module.hot.accept("./App", () => {
    const NextApp = require("./App").default;
    ReactDOM.render(
      <React.StrictMode>
        <App />
      </React.StrictMode>,
      rootId
    );
  });
}

Handling styles in webpack you can see follow

npm i -D sass-loader css-loader style-loader

Setting up webpack options that are appropriate to your environment

Before we set up the loaders, we need to separate our settings. When shipping to manufacturing, we want the packages to be as light as feasible. In terms of development, though, we aren’t as concerned. As a result, in both modes, we’d handle stylesheets differently. Let’s get started with the environment-specific configurations.

mkdir build-utils
npm i -D webpack-merge

Replace the code in webpack.config.js with the following

const path = require("path");
   const webpack = require("webpack");
   const { merge } = require("webpack-merge");
   const HtmlWebpackPlugin = require("html-webpack-plugin");
   const modeConfiguration = env => require(`./build-utils/webpack.${env}`)(env);
   
   module.exports = ({ mode } = { mode: "production" }) => {
       console.log(`mode is: ${mode}`);
   
       return merge(
           {
               mode,
               entry: "./src/index.js",
               devServer: {
                   hot: true,
                   open: true
               },
               output: {
                   publicPath: "/",
                   path: path.resolve(__dirname, "build"),
                   filename: "bundle.js"
               },
               module: {
                   rules: [
                       {
                           test: /\.(js|jsx)$/,
                           exclude: /node_modules/,
                           loader: "babel-loader"
                       }
                   ]
               },
               plugins: [
                   new HtmlWebpackPlugin({
                       template: "./public/index.html"
                   }),
                   new webpack.HotModuleReplacementPlugin()
               ]
           },
           modeConfiguration(mode)
       );
   };

Configuring production-specific settings

npm i -D mini-css-extract-plugin

Then, under build utils/webpack.production.js, add the following code:

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = () => ({
    output: {
        filename: "production.js"
    },
    module: {
        rules: [
            {
                test: /\.sa?css$/,
                use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"]
            }
        ]
    },
    plugins: [new MiniCssExtractPlugin()]
});

Even if it isn’t optimised, we can now see our CSS file in the output folder. We can use plugins like optimize-css-assets-webpack-plugin and uglifyjs-webpack-plugin to minify CSS.

To install the plugins that will help us improve our CSS, run the following commands:

npm i -D optimize-css-assets-webpack-plugin uglifyjs-webpack-plugin

Update the webpack.production.js file with the code below:

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");

module.exports = () => ({
    devtool: "nosources-source-map",
    output: {
        filename: "production.js"
    },
    optimization: {
        minimizer: [
            new UglifyJsPlugin({
                cache: true,
                parallel: true,
                sourceMap: true // set to true if you want JS source maps for css
            }),
            new OptimizeCSSAssetsPlugin({})
        ]
    },
    module: {
        rules: [
            {
                test: /\.sa?css$/,
                use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"]
            }
        ]
    },
    plugins: [new MiniCssExtractPlugin()]
});

Then, start your project you can see the below code,

npm run dev

Submit a Comment

Your email address will not be published. Required fields are marked *

Subscribe

Select Categories