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:
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')
)
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>
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'
}
)
]
}
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
}
}
)
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
}
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'
}
)
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"
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"
]
}
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"
}
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)