DEV Community

roggc
roggc

Posted on

Say goodbye to create-react-app 🧐

In this post, I will show you how to create a site (react app) with webpack and webpack-dev-server. There is no need for express. With webpack-dev-server you can develop your app and with webpack you build it in order to be deployed as static files (the ones produced by webpack building process).
Also, we will be using react-router-dom and we will see how to maintain routes when doing a complete refresh of the page.
So let's start. 🤘🎉
Here is my project structure:
Alt Text
In index.js file (in src folder) we have:

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

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

We are importing favicon.ico which will be used by file-loader in webpack configuration file to load this file on to the output folder (that is, on dist folder, together with other static files as main.js and index.html).
Now let's see content of index.html file (in public folder):

<!DOCTYPE html>
<html>
  <head>
    <title>site1</title>
  </head>
  <body>
    <div id='app'></div>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

Let's begin at looking to webpack configuration files.
webpack.common.js is as follows:

import {CleanWebpackPlugin} from 'clean-webpack-plugin'
import HtmlWebpackPlugin from 'html-webpack-plugin'

export default
{
  entry: './src/index.js',
  module:
  {
    rules:
    [
      {
        use: 'babel-loader',
        test: /\.js$/,
        exclude: /node_modules/
      },
      {
        test: /\.(png|jpe?g|gif|ico)$/i,
        use:
        [
          {
            loader: 'file-loader',
            options:
            {
              name: '[name].[ext]'
            }
          }
        ]
      }
    ]
  },
  plugins:
  [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin
    (
      {
        template:'./src/public/index.html'
      }
    )
  ]
}
Enter fullscreen mode Exit fullscreen mode

It has the entry point at ./src/index.js. It uses CleanWebpackPlugin to clean the folder before putting output in it and uses HtmlWebpackPlugin to include in the output the html file indicated in template field.
This is a common webpack configuration file, which means it will be used by webpack-dev-server and webpack (that is, for development and production or build process).
Now let's see webpack.dev.js:

import merge from 'webpack-merge'
import common from './webpack.common.js'

export default
merge
(
  common,
  {
    mode:'development',
    devServer:
    {
      historyApiFallback: true
    }
  }
)
Enter fullscreen mode Exit fullscreen mode

As we can see it adds to the common file two more configuration fields. The one which is mode:'development' it is self explanatory. The one which is

devServer:
{
  historyApiFallback: true
}
Enter fullscreen mode Exit fullscreen mode

means to keep the routes when refreshing the page. That is, let's say we are in /about page (remember, we are using react-router-dom in our project) and we do a reload of the page. We doesn't want to get error cannot get /about so with that configuration, while developing, we would not get this error, we will get a correct reload of the /about page.
Now let's see webpack.prod.js:

import merge from 'webpack-merge'
import common from './webpack.common.js'

export default
merge
(
  common,
  {
    mode:'production'
  }
)
Enter fullscreen mode Exit fullscreen mode

It doesn't add any special field, only it tells that it is production mode.
So we are ready to see at the scripts in the package.json file:

"transpile-wp": "babel wp -d wpt",
"start": "npm run transpile-wp && webpack-dev-server --open --config wpt/webpack.dev.js",
"build": "npm run transpile-wp && webpack --config wpt/webpack.prod.js"
Enter fullscreen mode Exit fullscreen mode

The first one (transpile-wp) it just transpile with babel the wp folder to wpt folder. start script it is meant for development and build script for production. As you can see for development we run webpack-dev-server, which opens a page in the browser pointing to localhost:8080 and gives us live reloading so we can develop fast. The second one uses webpack to build (bundle) the project. The output will be in dist folder.
In the case of production, it depends on the hosting service if it offers to us to keep the routes while reloading. For example, in firebase there is an option to configure this (you get asked about it when using the CLI).
Before finishing, and for the sake of completeness, we will see .babelrc:

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

and also let's take a look at dependencies in order to let you know what to install:

  "dependencies": {
    "@babel/cli": "^7.6.4",
    "@babel/core": "^7.6.4",
    "@babel/preset-env": "^7.6.3",
    "@babel/preset-react": "^7.6.3",
    "babel-loader": "^8.0.6",
    "clean-webpack-plugin": "^3.0.0",
    "file-loader": "^4.2.0",
    "html-webpack-plugin": "^3.2.0",
    "react": "^16.11.0",
    "react-dom": "^16.11.0",
    "react-router-dom": "^5.1.2",
    "webpack": "^4.41.2",
    "webpack-cli": "^3.3.9",
    "webpack-merge": "^4.2.2"
  },
  "devDependencies": {
    "webpack-dev-server": "^3.9.0"
  }
Enter fullscreen mode Exit fullscreen mode

So I think this is pretty much all about it. If you have any doubt or want to correct me at any point, please let me know.
As you can see we don't need express to develop react apps, we just use webpack and webpack-dev-server to develop sites that will be deployed as static files (html and js).
Thanks for reading!!! 👋

Top comments (0)