How to handle 404 error request in vuejs SPA with nginx server

GustavMahler picture GustavMahler · Sep 24, 2018 · Viewed 8.1k times · Source

I have set up my vue-cli version 3 SPA so that any requests not found in my routes.js file will default to my 404 view as shown in the official documentation:

Inserted near bottom of routes.js file:

{ // catches 404 errors
  path: '*',
  name: '404',
  component: () => import(/* webpackChunkName: "NotFoundComponent" */ './views/NotFoundComponent.vue'),
},

Inserted into nginx configuration file:

location / {
  try_files $uri $uri/ /index.html;
}

This successfully alerts the user that the page they requested doesn't exist.

My Question:

I would like for the error 404 component to return a 404 response header (it current returns the 200 status code) and also log this error to the nginx error.log file. I imagine this is only possible through using nginx configuration. Has anyone achieved this goal?

I noticed that this issue is addressed in the following page in the vue-cli official docs, but it only is concerned with node express servers and not nginx: https://router.vuejs.org/guide/essentials/history-mode.html#caveat

Answer

Max Sinev picture Max Sinev · Sep 24, 2018

I think it is similar to Node solution - you should repeat all your routes in nginx config to return 404 status code correctly, the main idea is that you should use "equals" modifier in locations and define error_page to return same index.html file but with 404 status code, example:

server {
    listen       80;
    server_name  localhost;
    root /my/dir/with/app
    error_page  404 /index.html;

    location = / {
        try_files $uri $uri/ /index.html;
    }

    location = /books {
        try_files $uri $uri/ /index.html;
    }

    # example nested page
    location = /books/authors {
        try_files $uri $uri/ /index.html;
    }

    # example dynamic route to access book by id
    location ~ /books/\d+$ {
        try_files $uri $uri/ /index.html;
    }
}

Probably this config can be simplified or improved because I am not very good at nginx configuration but it works.