Setup React with webpack

Usually we use the command npx create-react-app my-app to create a React project, this command creates a project with a defined structure and is not suitable to existing projects that have their own project folder structure. In the case you want to integrate React into a existing project or you want to have your own project folder structure you can setup React with webpack to have this flexibility.

This post will be about setting up a React project using webpack and babel by creating as an example a html file with a button and some text using React.

We are going to go step by step but the final file structure should look like this:

  | - .babelrc
  | - index.html
  | - dist
  |  | - index.js
  |  | - index.js.map
  | - js
  |  | - text.jsx
  |  | - button.jsx
  |  | - index.js
  | - node_modules
  | - webpack.config.js
  | - package-lock.json
  | - package.json

Start by creating a project:

Webpack will use babel to process javascript and React code .jsx.

{
  "presets": [
    "@babel/preset-env",
    "@babel/preset-react"
  ]
}
const path = require('path');
const webpack = require("webpack");

module.exports = {
    mode: 'development',
    entry: {
        'index':'./js/index.js',
    },
    module: {
        rules: [{
            test: /\.(jsx)$/,
            exclude: path.resolve(__dirname, "node_modules"),
            use: ['babel-loader']
        }]
    },
    output: {
        libraryTarget: "umd",
        filename: '[name].js',
        path: path.resolve(__dirname, 'dist'),
    },
    resolve: {
        extensions: ['.js', '.jsx'],
    },
    devtool: 'source-map',
    externalsPresets: {
        node: true,
    },
};

Now lets start creating the html and javascript files, as an example lets create a button and a paragrahp in react.

import React from 'react';

const button = (props) => {
    return(
        <button onClick={()=>{alert("button clicked!")}}>test</button>
    )
}

export default button
import React from 'react';

const text = (props) => {
    return(
        <p>Some text</p>
    )
}

export default text
import ReactDOM from 'react-dom'

import text from './text'
import button from './button'

ReactDOM.render(button(), document.querySelector("#button"))
ReactDOM.render(text(), document.querySelector("#text"))
<!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">
    <title>Document</title>
</head>
<body>

    <div id="button"></div>
    <div id="text"></div>
    <script src="/dist/index.js"></script>
</body>
</html>

We need now create the npm scripts to build the javascript files. Lets add the file package.json in the script section the following entries:

"scripts": {
    "webpack": "webpack --mode=production",
    "webpack-watch": "webpack -w"
  }

The final package.json should look similar to this:

{
  "name": "tmp",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "webpack": "webpack --mode=production",
    "webpack-watch": "webpack -w"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/preset-env": "^7.16.4",
    "@babel/preset-react": "^7.16.0",
    "babel": "^6.23.0",
    "babel-loader": "^8.2.3",
    "webpack": "^5.64.4",
    "webpack-cli": "^4.9.1"
  },
  "dependencies": {
    "react": "^17.0.2",
    "react-dom": "^17.0.2"
  }
}

Now if you serve the files you should see a button and some text in the browser. You can serve the files with the command python3 -m http.server or with php -S 127.0.0.1:8000