Vue History Mode - Support Legacy Hash URLs
When we first launched the boot.dev’s single-page-app, we were using Vue Router’s default hash routing. Hash routing looks ugly to the end-user, and when you want to be able to share parts of your app via direct link those hashes can get really annoying.
We have since moved to the newer HTML5 History Mode which doesn’t have that obnoxious hash in the route. We had a bit of trouble coming up with a clean way to redirect those old hash routes to the new ones, however, so now that we’ve solved it we will share our findings.
At the time of writing we have the following routes, you probably have something similar:
import Vue from "vue";
import VueRouter from "vue-router";
import Courses from "../views/Courses.vue";
import CourseProduct from "../views/CourseProduct.vue";
import Profile from "../views/Profile.vue";
import Exercise from "../views/Exercise.vue";
import Store from "../views/Store.vue";
import Certificates from "../views/Certificates.vue";
import Dashboard from "../views/Dashboard.vue";
import Certificate from "../views/Certificate.vue";
import Login from "../views/Login.vue";
import Playground from "../views/Playground.vue";
Vue.use(VueRouter);
const routes = [
{
path: "/",
name: "Login",
component: Login,
},
{
path: "/dashboard",
name: "Dashboard",
component: Dashboard,
children: [
{
path: "courses",
name: "Courses",
component: Courses,
},
{
path: "course_product/:courseUUID",
name: "CourseProduct",
component: CourseProduct,
},
{
path: "exercise/:courseUUID/:moduleUUID?",
name: "Exercise",
component: Exercise,
},
{
path: "store",
name: "Store",
component: Store,
},
{
path: "profile",
name: "Profile",
component: Profile,
},
{
path: "certificates",
name: "Certificates",
component: Certificates,
},
],
},
{
path: "/certificate/:userUUID/:courseUUID",
name: "Certificate",
component: Certificate,
},
{
path: "/playground/:lang",
name: "Playground",
component: Playground,
},
];
const router = new VueRouter({
mode: "history",
routes,
});
export default router;
Our goal is to redirect all of our old hash based (#) routes to the new non-hash versions. For example:
boot.dev/#/playground/go –> boot.dev/playground/go
All we do is add the following to our router:
// Redirect if path begins with a hash (ignore hashes later in path)
router.beforeEach((to, from, next) => {
// Redirect if fullPath begins with a hash (ignore hashes later in path)
if (to.fullPath.substr(0, 2) === "/#") {
const path = to.fullPath.substr(2);
next(path);
return;
}
next();
});
The full code:
import Vue from "vue";
import VueRouter from "vue-router";
import Courses from "../views/Courses.vue";
import CourseProduct from "../views/CourseProduct.vue";
import Profile from "../views/Profile.vue";
import Exercise from "../views/Exercise.vue";
import Store from "../views/Store.vue";
import Certificates from "../views/Certificates.vue";
import Dashboard from "../views/Dashboard.vue";
import Certificate from "../views/Certificate.vue";
import Login from "../views/Login.vue";
import Playground from "../views/Playground.vue";
Vue.use(VueRouter);
const routes = [
{
path: "/",
name: "Login",
component: Login,
},
{
path: "/dashboard",
name: "Dashboard",
component: Dashboard,
children: [
{
path: "courses",
name: "Courses",
component: Courses,
},
{
path: "course_product/:courseUUID",
name: "CourseProduct",
component: CourseProduct,
},
{
path: "exercise/:courseUUID/:moduleUUID?",
name: "Exercise",
component: Exercise,
},
{
path: "store",
name: "Store",
component: Store,
},
{
path: "profile",
name: "Profile",
component: Profile,
},
{
path: "certificates",
name: "Certificates",
component: Certificates,
},
],
},
{
path: "/certificate/:userUUID/:courseUUID",
name: "Certificate",
component: Certificate,
},
{
path: "/playground/:lang",
name: "Playground",
component: Playground,
},
];
const router = new VueRouter({
mode: "history",
routes,
});
// Redirect if path begins with a hash (ignore hashes later in path)
router.beforeEach((to, from, next) => {
// Redirect if fullPath begins with a hash (ignore hashes later in path)
if (to.fullPath.substr(0, 2) === "/#") {
const path = to.fullPath.substr(2);
next(path);
return;
}
next();
});
export default router;
Related Articles
How to Rerender a Vue Route When Path Parameters Change
Jul 07, 2020 by Lane Wagner - Boot.dev co-founder and backend engineer
In single-page apps that use the Vue Router, it’s common to create a path parameter that changes the behavior of a route. Often a problem occurs however when a user alters the path manually in the address bar. Manually changing the URL does not rerender the view! This can cause unexpected behavior because mounted() hooks don’t fire and nested components don’t reload.
Simple Setup - Vue Linting in VS Code
Jun 17, 2020 by Lane Wagner - Boot.dev co-founder and backend engineer
I’m a gopher by nature, so I expect consistent styling and linting in my codebases. More importantly, I don’t like to think about styling. I like to type haphazardly and then have my editor apply styles automatically on save (ctrl+s, cmd+s). If you are the same way, hopefully, this will help you in your next Vue.js project.