VueJS dev serve with reverse proxy

Marko Mitranić
Sep 28, 2019 · 6 min read

Original article available at: https://medium.com/homullus/vuejs-dev-serve-with-reverse-proxy-cdc3c9756aeb

The article was updated with a VERY simplified setup, thanks to the magic science of looking at source code. You can find it at the bottom.

I came upon a silly problem as i was setting up a new project for my teammates. The project is an open source weather/clothes up, and if that doesn’t explain much, just visit the repo or website: http://kaputtweather.com


VueJS setup

It literally spawns its own UI, and i’m not kidding here. Talk about useless overhead instead of putting efforts into quality.

Anyways, you just create a project and later run the ubiquitous yarn serveor yarn build. The problem is right there, you just don’t see it yet.

There is no watch…

Boo. We don’t want to wait for 500ms polling rate like peasants, lets make our own server && our own watch system.

The serve command was made in such a way that it spawns Vue’s own local server on port 8080, and builds no visible files (all files are generated on runtime). If you want to reap the benefits of HMR or even auto-reload you will have to use their server. I have nothing against this, but if you’re going to limit us in such a way, you must create flexible command line flags, which they did not. This is stupid, as no two infrastructure setups are the same nor they have the same needs. But i guess thats what you get for using a noob friendly tool for a supposedly simple task.

Anyways, my setup required me to serve stuff over Nginx in both dev and prod, so i did the following:

  1. Split dev/prod server config targets in my Dockerfile. (will explain better in the next post) (tldr; use a slightly different .conf for nginx setup on dev.)
  2. Dev config would not use default / block, which usually points to the build/dist folder, but will instead define a proxy to the node server on the other container.

1. a simple Nginx Proxy

location / {
proxy_pass http://localhost:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_redirect off;
proxy_connect_timeout 90s;
proxy_read_timeout 90s;
proxy_send_timeout 90s;
}

This will run my Nginx as it usually would, with all other servers and blocks intact, but will proxy all requests that hit this particular block through Nginx and to the Vue server found at localhost:8080. So from the viewpoint of Vue, it is indeed running on kaputtweather.com domain’s root.

You can find a similar example here:

2. Invalid Host header

location / {
proxy_pass http://localhost:8080/;
proxy_set_header Host localhost;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host localhost;
proxy_set_header X-Forwarded-Server localhost;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_redirect off;
proxy_connect_timeout 90s;
proxy_read_timeout 90s;
proxy_send_timeout 90s;
}

What we usually do on backend is that our apps watch out for X-Forwarded-Host (and similar) headers that can be hardcoded in nginx. Just swap all the Host references and hardcode them to localhost. Vue server will start to think that we are using it in localhost domain, and will allow access. Yay.

3. Sockets and Hot Module Replacement

location /sockjs-node/ {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
# And now all the stuff from above, again.proxy_set_header Host localhost;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host localhost;
proxy_set_header X-Forwarded-Server localhost;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_redirect off;
proxy_connect_timeout 90s;
proxy_read_timeout 90s;
proxy_send_timeout 90s;
}

Needless to say, this should only be used in dev environment, if you want to use it in prod, i would suggest properly learning Webpack configuration instead. If you need more info i would suggest this read:

A note about CORS & CORB on Nginx Proxy

proxy_hide_header Access-Control-Allow-Origin;
add_header Access-Control-Allow-Origin "http://kaputtweather.com";

By adding this to our server block, we are removing header that was received from the proxy, and replacing it with our own hardcoded domain name.


Host Header + HMR: UPDATE (28.09.2019)

I could smell some non-standard behaviour specific to JS ecosystem so i jumped into Webpack Dev server code. As you can observe, someone knew about the standard usage but didn’t really care to cover all use cases. They were checking only the Origin header (which btw is not usually used for this type of thing). This simplifies our setup quite a bit. If WebpackDevServer is not really looking at all the standard headers anyway, i can just kill them off:

location / {
proxy_pass http://kaputt_node:8080/;
proxy_set_header Host localhost;
proxy_set_header Origin localhost;
proxy_hide_header Access-Control-Allow-Origin;
add_header Access-Control-Allow-Origin "http://kaputtweather.com";
}

location /sockjs-node/ {
proxy_pass http://kaputt_node:8080;
proxy_set_header Host localhost;
proxy_set_header Origin localhost;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_hide_header Access-Control-Allow-Origin;
add_header Access-Control-Allow-Origin "http://kaputtweather.com";
}

Our server now still thinks it is run from localhost. Sockets do too.

You can see the full conf file on the GitHub repo:

Vue.js Developers

Helping web professionals up their skill and knowledge of Vue.js

Marko Mitranić

Written by

Full-Stack developer & University Lecturer

Vue.js Developers

Helping web professionals up their skill and knowledge of Vue.js

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade