47

I'm new to vuejs and I'm working on my first project with vue. I'm just wondering how I will route to my 404.vue component when the requested url is not found.

Any Idea?

Penny Liu
  • 15,447
  • 5
  • 79
  • 98
Kamga Simo Junior
  • 1,679
  • 2
  • 16
  • 30
  • 3
    Possible duplicate of [Vue-router redirect on page not found (404)](https://stackoverflow.com/questions/40193634/vue-router-redirect-on-page-not-found-404) – PatrickSteele Aug 10 '17 at 16:59

5 Answers5

121

In the routes declaration, I like to add this:

[
  ...  
  { path: '/404', component: NotFound },  
  { path: '*', redirect: '/404' },  
  ...  
]

Which will imply that if the user is navigated to a path which does not match any routes, it will be redirected to the "404" route, which will contain the "not found" message.

The reason I've separated it into 2 routes is so that you can also programmatically direct the user to the 404 route in such a case when some data you need does not resolve.

For instance, if you were creating a blog, you might have this route:

{ path: '/posts/:slug', component: BlogPost }

Which will resolve, even if the provided slug does not actually retrieve any blog post. To handle this, when your application determines that a post was not found, do

return this.$router.push('/404')

or

return router.push('/404')

if you are not in the context of a Vue component.

One thing to bear in mind though is that the correct way to handle a not found response isn't just to serve an error page - you should try to serve an actual HTTP 404 response to the browser. You won't need to do this if the user is already inside a single-page-application, but if the browser hits that example blog post as its initial request, the server should really return a 404 code.

g-wilson
  • 1,246
  • 1
  • 8
  • 4
  • How did you get this to work in the asyncData method inside a component? – Borjante Jan 31 '18 at 16:20
  • 3
    If you don't want it to retain the path in the browser do: `{ path: '/404', alias: '*', component: NotFound,}` – chaimp Jul 06 '18 at 04:36
  • 10
    This is bad for analytics/SEO. Search engine bots, Google Search Console, Google Analytics, etc. will not receive an actual 404 status code when the page is not found. – bumbleshoot Jul 07 '18 at 12:24
  • 6
    @torjinx what would be a SEO friendly option? – HJo Jul 12 '18 at 18:57
  • 1
    @HamishJohnson unfortunately I have not been able to find one yet... I'd be thrilled if someone else could chime in on this issue. – bumbleshoot Jul 12 '18 at 22:31
  • 6
    With a SPA app the server has already replied with 200 status code and then Vue loads and takes the user to the page. So you can't send a 404, as the server has already done a 200. You are best looking into server side rendering like Nuxt.js, as you probably can handle 404 that way. – PanPipes Sep 04 '18 at 11:49
  • You can redirect (using JavaScript) outside the single page application (to page with 404 status code provided by server). Otherwise, adding [noindex meta tag](https://support.google.com/webmasters/answer/93710?hl=en) may be search engine friendly solution. – Fenix Jul 10 '20 at 22:29
  • Couldn't you eliminate the 1st route by giving the 2nd a name? (and using the by name `$router.push` overload). – charles-allen Oct 21 '20 at 10:42
23

Now in Vue 3 path: '*' will not work. We have to use regex: /:catchAll(.*)

We can use directly instead of using path: "*"

{
    // path: "*",
    path: "/:catchAll(.*)",
    name: "NotFound",
    component: NotFound,
}

or

{
    path: '/404', name: 'NotFound', component: NotFound
},
{
    path: '/:catchAll(.*)', redirect:'404'
}

I got it from here

Penny Liu
  • 15,447
  • 5
  • 79
  • 98
Janardhan Singh
  • 447
  • 5
  • 12
18

There are a couple of ways to do this.

The most generic one is to check if the path matches any route before navigation and if not redirect to the Not found page.

router.beforeEach((to, from, next) => {
  if (!to.matched.length) {
    next('/notFound');
  } else {
    next();
  }
});

See JSFiddle.

Kuba Szymanowski
  • 1,307
  • 11
  • 25
  • 1
    Unlike `path: '*'`, this approach catches navigation to named routes that don't exist, for example `:to="{ name: 'InvalidRoute' }"` or `$router.push({ name: 'InvalidRoute' })`. However it does add a tiny overhead to *every* request. – charles-allen Oct 21 '20 at 10:53
10

After @g-wilson answer I went { path: '*', component: NotFound }. Might be useful if you don't want to make redirect.

Tarasovych
  • 2,228
  • 3
  • 19
  • 51
-18

For what I do is I give a class of http-found to the parent div all my component and I the mounted hook of the App.vue I check using jQuery or Javascript if there is any element with the class of http-found if not I redirect to my 404 page.

App.vue

mounted(){
   if(!$('.http-found')){
     this.$router.push('/404')
   }
}