Connecting Express backend to Javascript frontend


2 min read

This was something that confused me until recently.

The set up

Let's say you have your server running on port 8000 with this code:

app.get('/api', async (req, res) => {
  // get some data from an API

If you go to localhost:8000/api in your browser, it'll show you the data you've got from your API.

So all you need your front end to do is to navigate to that same location.

  const response = await fetch('http://localhost:8000/api');
  const data = await response.json();
  // do something with the data

Run your server on port 8000 and your client on another port and it gets the data all ok. So it works right? Not so much. If you open your front end on your phone, it won't get the data. Why? Because localserver doesn't make sense to your phone. You can't open localhost:8000/api on your computer, you have to do something like to get it to work.


Webpack has a solution for this: a proxy. It tells the client the server's location, so it can go there. You just have to add the details to your webpack config file.

devServer: {
    proxy: {
      '/api': 'http://localhost:8000',

And then in your client you just need to point it to /api:

  const response = await fetch('/api');
  const data = await response.json();
  // do something with the data

Which works. Except it gave me pause. In my server I have this line:

const port = process.env.PORT || 8000;

What this says is, if you have a port use it, otherwise use 8000. It's possible that the service you've uploaded to will choose its own port. In which case, this proxy won't help.

Serve client from the server

The solution for an uploaded/built site is to serve it from the server. In other words, when you go to localhost:8000 you get your index page.

const path = require('path');
app.use(express.static(path.resolve(__dirname, '..', 'public')));

In my case, the index folder is one folder up from the server, and then in the public folder.

The trouble with this is that if you're using a build tool that doesn't update the index, css and js files until you build it (rather than run it) then it won't help much.

In summary, it's simple, just a bit of a pain.