Simplifying React and Webpack setup. Easy-peasy boilerplate.

Quickly start your dev project with a simplified guide to setting up React and Webpack.

Imagine you're building a house. You can either use a ready-made blueprint that's easy to follow and gets the job done quickly, or you can design your own blueprint, which gives you more control but requires more effort.

Similarly, in web development, you can use a tool called Create React App, which is like the ready-made blueprint. It's great for beginners and makes starting a new project quick and easy.

But if you want to learn more about how things work behind the scenes, you can manually set up React and Webpack. It's like designing your own blueprint for the house. It may take more time and effort, but you'll gain a deeper understanding of how React and webpack work.

In this article, I'll guide you through the process of manually setting up React Webpack Boilerplate and webpack for your project. It's a great way to learn more about these tools and enhance your skills as a developer.

1. Create a folder and initialize a new Node.js project:

mkdir react-webpack-boilerplate
cd react-webpack-boilerplate
npm init -y

Inside the folder, you'll discover a file called "package.json" that contains the configuration for the project.

2. Now we can install React, ReactDOM, and Webpack as devDependencies:

If you're beginning new projects, make sure to install the latest versions of Node, NPM, and NVM. This helps avoid compatibility problems when installing the newest node modules. If you prefer to use a specific version, you'll need complete package.json to install those modules.

npm install --save-dev @babel/core @babel/preset-env @babel/preset-react babel-loader html-webpack-plugin webpack webpack-cli webpack-dev-server

3. And install React and Express as regular dependencies:

npm install express react react-dom

You'll notice that more than 540 packages were added in 12 minutes (yes, it takes time!). These node modules and their dependencies will likely consume more than 300 MB of space on your disk. In production, your project's dependencies will be compiled and bundled into a more compact file. This process typically involves minification, where unnecessary whitespace and comments are removed, and code is optimized for size and performance.

4. Let's create a basic structure (or you can simply clone the GitHub project):

mkdir dist
mkdir public
mkdir src
touch public/index.html
touch src/index.js
touch src/App.js
touch webpack.config.js
touch babel.config.js touch server.js

Basic HTML file (public/index.html)

    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>React App</title>
        </head>
        <body>
            <div id="root"></div>
        </body>
    </html>

Entry file to render React components (src/index.js)

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

    const root = ReactDOM.createRoot(document.getElementById("root"));

    root.render(
         <App />
    );

Basic React component (src/App.js)

    import React from 'react';

    function App() {
          return <h1>What's up, world?</h1>;
    }

    export default App;

Webpack configuration file (webpack.config.js)

        const path = require('path');
        const HtmlWebpackPlugin = require("html-webpack-plugin");
        
        module.exports = {
        	entry: {
        		boilerplate: './src/index.js'
        	},
          output: {
            filename: 'bundle.js',
            path: path.resolve(__dirname, 'dist')
          },
        	plugins: [
        		new HtmlWebpackPlugin({
        		  title: 'Boilerplate',
        		  filename: 'index.html',
        		  template: './public/index.html'
        		})
        	],
          devServer: {
            static: path.join(__dirname, 'public'),
            port: 9000,
            compress: true,
            open: true
          },
          mode: 'production',
          module: {
            rules: [
              {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: {
                  loader: 'babel-loader',
                  options: {
                    presets: [
                      '@babel/preset-env', 
                      '@babel/preset-react'
                    ]
                  }
                }
              }
            ]
          }
        };

Babel configuration file (babel.config.js)

    module.exports = {
        presets: ['@babel/preset-env', '@babel/preset-react']
    };

Express file to start the production server (server.js)

    const express = require('express');
    const path = require('path');

    const app = express();
    const PORT = process.env.PORT || 9001; 

    // Serve static files from the dist directory
    app.use(express.static(path.join(__dirname, 'dist')));

    // Start the server
    app.listen(PORT, () => {
                     console.log(`Server is running on http://localhost:${PORT}`);
    });

Add scripts to package.json:

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack serve --mode development --open",
    "build": "webpack --mode production"
  }

Now we can use commands for the dev:

npm test
npm start

And the prod server:

npm run build
node server.js

When you run these commands, you'll notice that npm run starts the development web server, npm build generates distribution files (/dist/ folder), and npm test displays the message "Error: no test specified" and exits. However, you can add more tests later to enhance your project's testing coverage.

Good luck!
May all your endeavors be successful, and may your code always run smoothly.
Best Regards,
Artem

433