DEV Community

roggc
roggc

Posted on

Minimal Webpack configuration to get React app

In this post, I will show you my implementation of Webpack, express, and babel to get react app working.
First, we are going to download everything we need. Let's start.

npm i @babel/cli @babel/core @babel/preset-env @babel/preset-react babel-loader express file-loader react react-dom webpack webpack-cli webpack-node-externals
Enter fullscreen mode Exit fullscreen mode

and

npm i --save-dev nodemon
Enter fullscreen mode Exit fullscreen mode

Your dependencies should look like the next picture:
react dependencies
After that, we are good to go.
My project structure will be as follows:
Alt Text
As you see we have an index.js file for the app component, another one for the client folder and another one for the server folder. Also, we have .babelrc, wpclient.config.js and wpserver.config.js. And last but not least we have an index.html file in the public folder.
Let's see all of these files and how they relate to each other. Also, we will have to see the scripts field in the package.json file.
Let's start for the index.js file in the app folder.

import React from 'react'

export default
()=>
<div>hello</div>
Enter fullscreen mode Exit fullscreen mode

As you see is a simple component in react. Now let's see the content of the index.js file in client folder.

import React from 'react'
import {render} from 'react-dom'
import App from './comps/app/index'
import './public/index.html'

render
(
  <App/>,
  document.getElementById('app')
)
Enter fullscreen mode Exit fullscreen mode

As you see it imports the index.html file, so let's see its content too.

<!DOCTYPE html>
<html>
 <head>
   <title>my app</title>
 </head>
 <body>
   <div id='app'></div>
   <script src='./bundle.js'></script>
 </body>
</html>
Enter fullscreen mode Exit fullscreen mode

As you see we place a script tag which references to a file ./bundle.js. That's the file webpack will make as the result of the bundle process and that will be placed in the dist folder under root project folder.
Last index.js file we see is the one in the server folder.

import express from 'express'

const app = express()
app.use(express.static('dist'))
const port=3000
app.listen(port,()=>console.log('listening on port '+port))
Enter fullscreen mode Exit fullscreen mode

As you can see it uses the content under dist folder, which is where webpack puts its output by default.
It rests us to see the webpack configuration files. The first one is wpclient.config.js.

export default
{
  entry: './src/client/index.js',
  output:
  {
    filename: './bundle.js'
  },
  module:
  {
    rules:
    [
      {
        use: 'babel-loader',
        test: /\.js$/,
        exclude: /node_modules/
      },
      {
        test: /\.(html)$/,
        use:
        {
          loader: 'file-loader',
          options:
          {
            name: './index.html',
          }
        }
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

Its entry point is ./src/client/index.js which we already have seen. Its output is in ./bundle.js which means in dist folder (webpack creates it if not exists). Then it uses babel-loader to deal with ES6 syntax. And last it uses file-loader to put index.html file into the dist folder too (together with the bundle.js file). It is for that reason we imported that file in the index.js file definition under client folder.
Now let's see the content of wpserver.config.js file.

import nodeExternals from 'webpack-node-externals'

export default
{
  target: 'node',
  externals: [nodeExternals()],
  entry: './src/server/index.js',
  output:
  {
    filename: '../index.js'
  },
  module:
  {
    rules:
    [
      {
        use: 'babel-loader',
        test: /\.js$/,
        exclude: /node_modules/
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

As you see it uses nodeExternals to tell not to use node_modules folder. It targets node and the entry point is of course ./src/server/index.js which we already have seen. The output ../index.js is relative to the dist folder under the root project, so it will create an index.js file under the root directory as output. That's the file the scripts in package.json will execute (that is, node and nodemon).
So we have seen all the files, it only rests us see .babelrc configuration file. Let's do that now.

{
  "presets":
  [
    "@babel/preset-env",
    "@babel/preset-react"
  ]
}
Enter fullscreen mode Exit fullscreen mode

Now we are ready to go. This means we must prepare the scripts to execute all those files. We do that in package.json. Let's see how.

  "scripts":
  {
    "transpile-wpserver": "babel wpserver.config.js -d wp",
    "transpile-wpclient": "babel wpclient.config.js -d wp",
    "bundle-server": "npm run transpile-wpserver && webpack --config wp/wpserver.config.js",
    "bundle-client": "npm run transpile-wpclient && webpack --config wp/wpclient.config.js",
    "start": "npm run bundle-client&& npm run bundle-server&& node index.js",
    "bundle-server-w": "npm run transpile-wpserver && webpack -w --config wp/wpserver.config.js",
    "bundle-client-w": "npm run transpile-wpclient && webpack -w --config wp/wpclient.config.js",
    "dev": "npm run bundle-client-w & npm run bundle-server-w & nodemon"
  }
Enter fullscreen mode Exit fullscreen mode

As you see what we do first is to transpile or compile webpack configuration files themselves before using (they are wrote using ES6 syntax). Those transpiled webpack configuration files will be kept under wp folder (which babel will create for us). Then we run webpack itself to produce the bundle. Finally we run node or nodemon (depending if we are developing or in production mode) to the index.js file which is the bundle produced by webpack in the case of the server file (the other one, the front end, will be under dist folder). As you see when running nodemon it is not necessary to specify the file because it defualts to index.js file under root directory, while when using node command it is necessary.

If you do all that you will have a React app up and running.
Thank you for reading.

Top comments (0)