Say goodbye to create-react-app 🧐
Tags: react
Published: 2019-10-27 23:06:51

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](https://thepracticaldev.s3.amazonaws.com/i/o5wlrutijjnz69kxvmrc.png)
In `index.js` file (in `src` folder) we have:
```javascript
import React from 'react'
import {render} from 'react-dom'
import App from './comps/app/index'
import './public/favicon.ico'

render
(
  <App/>,
  document.getElementById('app')
)
```
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):
```javascript
<!DOCTYPE html>
<html>
  <head>
    <title>site1</title>
  </head>
  <body>
    <div id='app'></div>
  </body>
</html>
```
Let's begin at looking to *webpack* configuration files.
`webpack.common.js` is as follows:
```javascript
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'
      }
    )
  ]
}
```
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`:
```javascript
import merge from 'webpack-merge'
import common from './webpack.common.js'

export default
merge
(
  common,
  {
    mode:'development',
    devServer:
    {
      historyApiFallback: true
    }
  }
)
```
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 
```javascript
devServer:
{
  historyApiFallback: true
}
```
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`:
```javascript
import merge from 'webpack-merge'
import common from './webpack.common.js'

export default
merge
(
  common,
  {
    mode:'production'
  }
)
``` 
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:
```javascript
"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"
```
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`:
```javascript
{
  "presets":
  [
    "@babel/preset-env",
    "@babel/preset-react"
  ]
}
```
and also let's take a look at dependencies in order to let you know what to install:
```javascript
  "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"
  }
```
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!!! 👋