Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue-router redirect on page not found (404)

I'm trying to redirect to 404.html on page not found using the router.beforeEach global hook, without much success (using Vueand Vue-Router 1.0):

router.beforeEach(function (transition) {     if (transition.to.path === '/*') {         window.location.href = '/404.html'     } else {         transition.next()     } }); 

This is not redirecting to page 404.html when a non-existing route is inserted, just giving me an empty fragment. Only when hard-coding some-site.com/* will it redirect to the expected some-site.com/404.html

I'm sure there's something very obvious here that I'm overlooking, but I cannot figure out what.


Please note that what I am looking for is a redirect to a new page, not a redirect to another route, which could be easily achieved by using router.redirect such as in these snippets:

router.redirect({     '*': '404' }) 

Whereas on my router.map, I could have the following:

 router.map({     '/404': {         name: '404'         component: {             template: '<p>Page Not Found</p>'         }     } }) 
like image 474
nunop Avatar asked Oct 22 '16 15:10

nunop


2 Answers

I think you should be able to use a default route handler and redirect from there to a page outside the app, as detailed below:

const ROUTER_INSTANCE = new VueRouter({     mode: "history",     routes: [         { path: "/", component: HomeComponent },         // ... other routes ...         // and finally the default route, when none of the above matches:         { path: "*", component: PageNotFound }     ] }) 

In the above PageNotFound component definition, you can specify the actual redirect, that will take you out of the app entirely:

Vue.component("page-not-found", {     template: "",     created: function() {         // Redirect outside the app using plain old javascript         window.location.href = "/my-new-404-page.html";     } } 

You may do it either on created hook as shown above, or mounted hook also.

Please note:

  1. I have not verified the above. You need to build a production version of app, ensure that the above redirect happens. You cannot test this in vue-cli as it requires server side handling.

  2. Usually in single page apps, server sends out the same index.html along with app scripts for all route requests, especially if you have set <base href="/">. This will fail for your /404-page.html unless your server treats it as a special case and serves the static page.

Let me know if it works!

Update for Vue 3 onward:

You'll need to replace the '*' path property with '/:pathMatch(.*)*' if you're using Vue 3 as the old catch-all path of '*' is no longer supported. The route would then look something like this:

{ path: '/:pathMatch(.*)*', component: PathNotFound }, 

See the docs for more info on this update.

like image 150
Mani Avatar answered Sep 23 '22 04:09

Mani


@mani's response is now slightly outdated as using catch-all '*' routes is no longer supported when using Vue 3 onward. If this is no longer working for you, try replacing the old catch-all path with

{ path: '/:pathMatch(.*)*', component: PathNotFound }, 

Essentially, you should be able to replace the '*' path with '/:pathMatch(.*)*' and be good to go!

Reason: Vue Router doesn't use path-to-regexp anymore, instead it implements its own parsing system that allows route ranking and enables dynamic routing. Since we usually add one single catch-all route per project, there is no big benefit in supporting a special syntax for *.

(from https://next.router.vuejs.org/guide/migration/#removed-star-or-catch-all-routes)

like image 33
Luca C Avatar answered Sep 19 '22 04:09

Luca C