I'm trying to redirect to 404.html on page not found using the router.beforeEach
global hook, without much success (using Vue
and 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>' } } })
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:
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.
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.
@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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With