Jordi Nebot
Jordi Nebot

Reputation: 3401

Vue SPA to force page reload when using vue-router navigation

Scenario:

I have a Vue2 SPA ready to replace a legacy LAMP website but PO would like to deploy it progressively (starting with just one single URL) to test user's reactions, analytics, ad revenue, etc.

We've built this architecture to allow this approach:

Architecture

It works. So, if you go to http://example.com/release-first (let's say this is the page we want to release publicly in the first place) CF returns the content from the S3, and any other URL is fetched from the legacy server.

But, of course, when you access /release-first you're in the SPA, and since most of the navigation is done with <router-link :to="">, you're trapped in the SPA and you can access the rest of the new version, which we don't want at this point.

Possible solutions I thought:

One solution could be to replace all <router-link> tags with standard <a> links that would force the browser to do a new petition to the CloudFront every time. That might work but I'd prefer not to do it because I have to change a lot of links and also because links are not the only way the user can move around (there's some form submission too, etc.)

So, I tried something like:

router.beforeEach((to, from, next) => {
    if (!/\/release-first\/?$/.test(to.path)) {
        window.location.href = `http://example.com${to.path}`  
        return;
    } else {
        next();
    }
});

This works fine in staging env (because it has a different subdomain, so it's redirecting to production) but if I try in production it doesn't work. I don't know if Vue hijacks the Location API or what, but it doesn't force a new petition to the CloudFront.

I've also tried with:

const absolutePath = `http://example.com${to.path}`;
window.history.pushState({ urlPath: absolutePath }, "", absolutePath);
window.location.reload();

But it doesn't work either... and I couldn't find in vue-router's Docs an option to force the page to reload on navigation. Any idea on how to achieve this?


Extra information requested in comments:

Upvotes: 3

Views: 1421

Answers (1)

Jordi Nebot
Jordi Nebot

Reputation: 3401

This is how I finally solved it:

router.beforeEach((to, from, next) => {
    if (
        window.location.host === "prod-env.example.com" &&
        /\/release-first/.test(from.path) &&
        !/\/release-first/.test(to.path)
    ) {
        let a = document.createElement("a");
        a.id = "forceReloadLink";
        a.href = to.path;
        document.querySelector("body").appendChild(a);
        document.getElementById("forceReloadLink").click();
    } else {
        next();
    }
});

Upvotes: 2

Related Questions