DIY Webpack Dev Server with Express
The best way to build a new project with Webpack is to run the
webpack-dev-server for local
development. Its turnkey solution to hot reloading is fantastic. But what
exactly is the webpack-dev-server
? In this episode we'll rebuild it from the
ground up using an express server and middleware.
A custom Node server like Express or Koa can give us flexibility to add further optimizations and customizations.
To begin, you may start from where we left off, or clone this git repo and checkout the right branch like so.
git clone git@github.com:lawwantsin/webpack-course.git
cd webpack-course
git checkout express1
npm install
We're going to remake the dev server as part of a larger plan for our web server. This step is crucial to the rest of the course. It's time to graduate from the premade binary to gain more control over our stack.
We'll start by adding Express.
npm install express
mkdir src/server
touch src/server/express.js src/server/main.js
In package.json
add a new command to your scripts object.
"scripts": {
...
"dev": "node src/server/main.js"
},
This will run the server whenever we type npm run dev
.
In src/server/main.js
require("babel-core/register")
require("./express.js")
What babel-core/register
does is it tells babel to process the code that
follows using babel's rules. In this case we want to use ES6 imports in our
server side code.
In src/server/express.js
import express from "express"
import path from "path"
const server = express()
const staticMiddleware = express.static("dist")
server.use(staticMiddleware)
const PORT = 8080
server.listen(PORT, () => {
console.log(`Server listening on http://localhost:${PORT}`)
})
If we run npm run dev
we see the output Server Listening on http://localhost:8080
in the terminal.
Oops, we've got no html now. That's because webpack's not building our main.js
anymore. Let's do it manually.
npm run build
Reload the browser and you'll see we've got styles back.
This is almost usable in production as is. But in development, we want the same live-reloading experience in express. So let's add that middleware right next to the static middleware.
In terminal:
npm install webpack-dev-middleware
In express.js
right above the staticMiddleware declaration.
...
const isProd = process.env.NODE_ENV === "production"
if (!isProd) {
const webpack = require("webpack")
const config = require("../../config/webpack.dev.js")
const compiler = webpack(config)
const webpackDevMiddleware = require("webpack-dev-middleware")(
compiler,
config.devServer
)
server.use(webpackDevMiddleware)
console.log("Middleware enabled")
}
const staticMiddleware = express.static("dist")
...
Note: Make sure you place the webpackDevMiddleware before the staticMiddleware.
We're only using webpack-dev-server in development anyway, so by wrapping it in
an isProd
we can keep our production server in the same file.
npm run dev
To restart the webpack dev server and if we change main.css
we can see that
webpack automatically rebuilds. But we still have to reload the page to see
results. Who wants that? Luckily, it's just 1 more additional piece of
middleware and we have hot module reloading.
npm install -D webpack-hot-middleware
Change 2 lines to add a whole bunch of websocket functionality to update live.
const webpackHotMiddlware = require("webpack-hot-middleware")(compiler)
server.use(webpackDevMiddleware)
server.use(webpackHotMiddlware)
There are 3 changes to your webpack.dev.js
:
- At the top add:
import webpack from "webpack"
- In the
devServer
object add thehot
option:
hot: true
- Add 2 plugins below the modules object:
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin()
]
We'll get more into plugins soon. For now we can think of them as additional processing that happen at the end of the compilation before output.
One last thing. We need to add a new file to src/main.js
. It should now look
like this:
require("babel-runtime/regenerator")
require("webpack-hot-middleware/client")
require("./main.css")
require("./images/link.jpg")
require("./index.html")
Now when we restart the server, we see that HMR is enabled
. In the Network Tab
of our DevTools:
Make changes to the main.css
file and see it updated live in the browser
without a refresh.
In Sum
In this article we traded the off-the-shelf webpack dev server for a custom express dev server. In so doing we basically dissected how the command-line tool does it.
git checkout express1-final
Next Up
Our goal is, as always to create an incredible developer's experience and in the next article we'll work on the server side to finish up our Hot reloading effort.