create-react-app and Express, together on Glitch
Tags: react, express, glitch, proxies
Published: 2020-02-14 15:52:54

[Glitch](http://glitch.com?utm_medium=weblink&utm_source=dev.to&utm_campaign=blog&utm_content=dev) is the fastest way to get an app or site up and running live on the web, but it runs apps on only one port. Sometimes you need more, like when you're building a [React front end](https://glitch.com/culture/react-starter-kit/?utm_medium=weblink&utm_source=dev.to&utm_campaign=blog&utm_content=dev) with create-react-app and the back-end with [Express](https://glitch.com/~hello-express?utm_medium=weblink&utm_source=dev.to&utm_campaign=blog&utm_content=dev). Here's how to work around this constraint, with a proxy middleware and some port-switching logic!

## The Problem

Remote development on Glitch has a lot of benefits — it's simply the fastest way to get an app or site up and running live on the web, abstracting away of a lot of the fiddly parts of web development. While this very much makes it a go-to for most ideas that I want to build, I will occasionally run into little speed-bumps that aren't really an issue in a typical local-development setup.

One such speed-bump is that Glitch only serves content on one port. This is typically not an issue, unless you're trying to run both a webpack development server for front-end work _and_ a back-end server in the same project, at the same time — you get one port for serving resources, but both the front-end and back-end servers each want their own port! This is a common scenario when you're building your front end with [create-react-app](https://create-react-app.dev/), and your back end with [Express](https://expressjs.com/). 

What's more — Glitch's watcher provides live previews of your changes to a file, but so does create-react-app's Webpack development server!

Ugh. Can't we all just get along?

(_Spoiler: Yes. Yes, we can._)

## The Solution

I ran into exactly this problem when our team built the [web app](https://capitol-royale.glitch.me) for Capitol Records' [_Capitol Royale_](https://capitolroyale.com) event in November.

When you create a Node app on Glitch based on the [hello-express starter app](https://glitch.com/~hello-express?utm_medium=weblink&utm_source=dev.to&utm_campaign=blog&utm_content=dev), the starter project includes a **server.js** file that implements a basic Express server. This server handles routing to various parts of your app, and is set up to listen on port 3000.<sup>1</sup>

Similarly, if you use `create-react-app` to, uh, create a React app, `react-scripts` starts a webpack development server that, by default, _also_ listens on port 3000.

So what happens when you're working on a React app, but you also want to add an Express backend?

Essentially, we got it working such that:

1. If you set your `start` script to `"npm run production"` in **package.json**, it will build the React app and Express will serve the static bundle over port 3000. _BUT!_
2. If you set your `start` script to `"npm run development"` in **package.json**, it will concurrently start the webpack dev server/watcher _and_ the Express server. The latter will be listening on port 3001, _but_ you don't need to change anything in your code because: proxies!

## 😲 WHAT IS THIS SORCERY‽

This works thanks to a couple of moving parts: a proxy that listens for requests on a certain port and forwards them to another, and a bit of scripting and server-side logic that checks for an environment variable to know which port to listen to. Let's dig in!

### The proxy

Since we only have one port to work with, we want to watch for requests to some endpoints and forward them through a proxy to our backend server.

If you create **src/setupProxy.js**, React will register it automatically when you start the development server ([details here](https://create-react-app.dev/docs/proxying-api-requests-in-development/#configuring-the-proxy-manually)). So, add this to your **src/setupProxy.js** file:

```javascript
const proxy = require("http-proxy-middleware");

// This proxy redirects requests to /api endpoints to
// the Express server running on port 3001.
module.exports = function(app) {
  app.use(
    "/api",
    proxy({
      target: "http://localhost:3001"
    })
  );
};
```

What React and the proxy are doing here, essentially, is working together to say, "okay, any request to `/api` _isn't_ a request for a static asset, so pass it on to the target" — that target being the Express server. Don't forget to add [`http-proxy-middleware`](https://github.com/chimurai/http-proxy-middleware) to your **package.json** file, since   **src/setupProxy.js** `require`s it.

Fun fact! "Globbing" is a weird-sounding word, but what it means is that just adding "`/api`" in the proxy is enough to correctly route "`/api/ping`", "`/api/user/:userid`", etc., to the target — we don't have to add every possible route in the function, which makes our lives much easier.

### The ports

With proxying in place, the port situation is less confusing now. However, Glitch will still only serve one port, so we have to do some switching based on what mode we're working in.

- In `development` mode, the webpack dev server listens on port `3000`, so we set Express to listen to port `3001`, and proxy any requests to `/api` endpoints through as described above.
- In `production` mode, there _is_ no webpack dev server, so we set Express to listen to port `3000`, and Express serves the static resources directly.

### The switching

Depending on whether you `npm run production` or `npm run development`, different servers and/or proxies are started, _and_ `NODE_ENV` is set to either `production` or `development` — you don't want to have to change this in an **.env** file.

Setting the value of `NODE_ENV` is best done in **package.json**'s `scripts`:

```json
"scripts": {
    "start": "npm run development",
    "development": "NODE_ENV=development concurrently --kill-others \"npm run client\" \"npm run server\"",
    "production": "npm run build && NODE_ENV=production npm run server",
    "client": "react-scripts start",
    "server": "node server/server.js",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  }
```

What we're doing in the above scripts is defining a `development` and a `production` script.

In `development`, we set the `NODE_ENV` to `development`, and use the [`concurrently`](https://github.com/kimmobrunfeldt/concurrently) package to run both the front-end Webpack server (`client`) and Express server (`server`) scripts at the same time. This is like opening two terminals on your local machine, running `npm run client` in one, and `npm run server` in the other.

In `production`, we build the React app, set the `NODE_ENV` to `production`, and then start the Express server.

That works great! However, there's still the issue of telling Express which port to use in each mode — we want it to use port 3001 in `development`, and port 3000 in `production`. We handle this in **server/server.js**, where there's a bit of logic towards the end of the file that checks the value of `NODE_ENV` and sets the listener's port appropriately:

```javascript
let port;
console.log("❇️ NODE_ENV is", process.env.NODE_ENV);
if (process.env.NODE_ENV === "production") {
  port = process.env.PORT || 3000;
  app.use(express.static(path.join(__dirname, "../build")));
  app.get("*", (request, response) => {
    response.sendFile(path.join(__dirname, "../build", "index.html"));
  });
} else {
  port = 3001;
  console.log("⚠️ Not seeing your changes as you develop?");
  console.log(
    "⚠️ Do you need to set 'start': 'npm run development' in package.json?"
  );
}

const listener = app.listen(port, () => {
  console.log("❇️ Express server is running on port", listener.address().port);
});
```

Specifically, if `NODE_ENV=development`, the port Express listens on is set to `3001` and serving assets is delegated to the webpack dev server. We also print a message to the console, suggesting that if you're not seeing your changes as you develop, you might need to check that you've changed the `start` script in **package.json** to `npm run development`.

Likewise, if `NODE_ENV=production`, the port Express listens on is set to `3000` and a route is added to serve the static resources from the `/build` directory.

## 👀 Watching the Watcher

We've now got requests going where they need to go: in development mode, we're serving the webpack development server and proxying API requests to the Express server, and in production mode, we have the Express server handling both the API endpoints and serving the static resources. But we're not quite done yet!

There's one last thing we want to sort out with our project: file watching. Both the Webpack development server _and_ Glitch watch for changes to files, and automatically update the live app as you type. This rapid feedback look is really handy for previewing your modifications, but we don't want the watchers to interfere with each other!

The Webpack watcher only kicks in when the project is in `development` mode, and watches for changes in the **/src** directory. We can't really reach in and change much there, but we don't need to — all we really need is to tell the Glitch watcher to only look at what's changing in the **/server** folder.

We do that by adding a special [**watch.json**](https://glitch.com/help/restart/) file in the project root:

```json
{
  "install": {
    "include": [
      "^package\\.json$",
      "^\\.env$"
    ]
  },
  "restart": {
    "exclude": [
      "^public/",
      "^src/"
    ],
    "include": [
      "^server/",
      "^watch\\.json$"
    ]
  },
  "throttle": 100
}
```

Here, we specify a couple of conditions for Glitch's watcher.

1. We only want to run `install` scripts when changes are made to the **package.json** and **.env** files. Installation can take a while, so we don't want to trigger it with any other changes.
2. We only want to `restart` the project when changes are made in the **/server** folder, or to the **watch.json** file. We're including **watch.json** in case we need to kick off a restart — a change to the `throttle` value will trigger this. We're also explicitly ignoring any files in the **/public** and **/src** directories from kicking off a restart — we only want the Webpack watcher to handle these files.
3. We're setting a `throttle` of 100, which means that the Glitch watcher will wait 100 milliseconds before restarting anything. If that seems too quick, you can increase it.

And with those changes, we're ready to go! If you want a one-click solution, remix this starter app to get going:

{% glitch starter-cra-and-express %}

Add API routes in **server/server.js** (I've started you off with a `GET` route to `/api/ping` for checking that the server is up) and build your React app in the **src** directory (the `create-react-app` starter app you know and love is already there for you to start hacking on).

Have fun, and don't forget to show us what you build!

---

<!-- Footnotes -->
<sup>1</sup> There's some subtlety to port handling in Glitch that, for the purposes of this article, I'm going to skip explaining. Long story short, Glitch does some work in the background and actually serves apps running on a couple of ports; the default `~hello-node` project's Express server uses 3000, but ports 8000 and 8080 would also work, for example.