Automatically refresh the browser on Node / Express server changes &#x1F680;
Tags: javascript, express, livereload, nodemon
Published: 2021-06-08 15:03:48

One of the first things that most developers learn when starting with ExpressJS is using [Express Generator](https://expressjs.com/pt-br/starter/generator.html) to create a basic app structure. After install, a simple working app can be seen just running `npm start` in the command line. Other javascript frameworks like ReactJs, have something similar with [Create React App](https://reactjs.org/docs/create-a-new-react-app.html).

Who already started a ReactJs project knows how good it is to make changes in source code with your favorite editor, and see all of them to be updated in the browser automatically. However, Express Generator unfortunately doesn’t give us that behaviour by default. 

**Create React App** &#x1F642;
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/firicel97qynbge42drh.gif)

**Express Generator** &#x1F614;
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3jwdmym1o386qwwf9kj5.gif)

To do that, let's make a few changes to our Express server so that it behaves the way we need it. Let's code! &#x1F91F;

## 1) Create an ExpressJS server from scratch 

Install the express-generator package:
```
npm install -g express-generator
```

Create the app:
```
express express-browser-reload --view=hbs
```
* `express-browser-reload`: the folder name where the files will be created inside;
* `--view=hbs`: the default template engine used to create the project (I like handlebars .hbs);

Install dependencies:
```
npm install
```

Start your Express.js app at http://localhost:3000/ :
```
npm start
```

Now we have the above example running.

## 2) Get the power! 

Let’s add some extra packages to the project to achieve our goal: 
```
npm i -D nodemon livereload connect-livereload
```
* `-D`: install packages as dev dependencies is a good practice here;

## 3) Restart the server on changes

Currently, our server doesn't even restart when we make changes in source code. Our first step is to set Nodemon to watch those changes. In the `package.json`, add `watch` script to enable it:

**package.json**

```json
"scripts": {
  "start": "node ./bin/www",
  "watch": "nodemon"
},
```
By default, Nodemon watches for changes only to files with these extensions:

- js
- mjs
- json

If you want to watch for changes in all project files, set additional param `--ext` with `*` or specific extensions separated with commas `js,hbs,css`:

**package.json**

```json
"scripts": {
  "start": "node ./bin/www",
  "watch": "nodemon --ext *"
},
```
From now on, run the server with `npm run watch` instead of `npm start`.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j4uxucvcbq4tek6nqv33.gif)

Now your ExpressJS server restarts automatically on any file changes, but not yet updates the browser when they occur.

## 4) Refresh the browser on changes

In the `app.js` file, three main changes must be done.

**app.js**

```js
var livereload = require("livereload");
var connectLiveReload = require("connect-livereload");
```

Import `livereload` and `connect-livereload` to enable the feature in our server.

**app.js**

```js
const liveReloadServer = livereload.createServer();
liveReloadServer.server.once("connection", () => {
  setTimeout(() => {
    liveReloadServer.refresh("/");
  }, 100);
});
```

Create a Livereload server and listen to connection events. When Nodemon restarts the ExpressJS server on changes, Livereload recreates the server and sends to the browser a refresh command when connected `liveReloadServer.refresh("/");`.

**app.js**

```js
app.use(connectLiveReload());
```

Lastly, we use connect middleware for adding the Livereload script to the response.

After all modifications, our `app.js` will be like this:

**app.js (done)**

```js
var createError = require("http-errors");
var express = require("express");
var path = require("path");
var cookieParser = require("cookie-parser");
var logger = require("morgan");
var livereload = require("livereload");
var connectLiveReload = require("connect-livereload");

var indexRouter = require("./routes/index");
var usersRouter = require("./routes/users");

const liveReloadServer = livereload.createServer();
liveReloadServer.server.once("connection", () => {
  setTimeout(() => {
    liveReloadServer.refresh("/");
  }, 100);
});

var app = express();

app.use(connectLiveReload());

// view engine setup
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "hbs");

app.use(logger("dev"));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, "public")));

app.use("/", indexRouter);
app.use("/users", usersRouter);

// catch 404 and forward to error handler
app.use(function (req, res, next) {
  next(createError(404));
});

// error handler
app.use(function (err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get("env") === "development" ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render("error");
});

module.exports = app;
```

.. and the magic happens!

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j2sp8z20w6puamxpk85n.gif)

*Note that a javascript is added to our HTML page and that points to the server created by Livereload on port 35729*.

## Conclusion

Eliminating repetitive actions during development helps to optimize our performance as developers. Taking a few minutes to properly setup our application before you even start development is something you should always consider.

[Get this working example in Github](https://github.com/cassiolacerda/express-browser-reload).