Vue SPA 在使用 vue-router 导航时强制重新加载页面
Vue SPA to force page reload when using vue-router navigation
场景:
我有一个 Vue2 SPA 准备好替换遗留 LAMP 网站,但 PO 想逐步部署它(从一个 URL 开始)以测试用户的反应、分析、广告收入等
我们构建了这个架构来支持这种方法:
有效。因此,如果您转到 http://example.com/release-first(假设这是我们首先要公开发布的页面)CF returns 来自 S3 的内容,以及任何其他 URL 被提取来自旧服务器。
但是,当然,当您访问 /release-first
时,您处于 SPA 中,并且由于大部分导航都是使用 <router-link :to="">
完成的,您 被困 在 SPA 中,您可以访问新版本的其余部分,这是我们目前不需要的。
我认为可能的解决方案:
一种解决方案是用标准 <a>
链接替换所有 <router-link>
标签,这将强制浏览器每次都向 CloudFront 执行新的请求。这可能行得通,但我不想这样做,因为我必须更改很多链接,还因为链接不是用户移动的唯一方式(还有一些表单提交等)
所以,我尝试了类似的方法:
router.beforeEach((to, from, next) => {
if (!/\/release-first\/?$/.test(to.path)) {
window.location.href = `http://example.com${to.path}`
return;
} else {
next();
}
});
这在 staging
env 中工作正常(因为它有一个不同的子域,所以它重定向到生产)但是如果我在生产中尝试它不起作用。我不知道 Vue 是劫持了 Location API 还是什么,但它不会强制向 CloudFront 发出新的请愿书。
我也尝试过:
const absolutePath = `http://example.com${to.path}`;
window.history.pushState({ urlPath: absolutePath }, "", absolutePath);
window.location.reload();
但它也不起作用...而且我在 vue-router
的 Docs 中找不到强制页面在导航时重新加载的选项。关于如何实现这一目标的任何想法?
评论中要求的额外信息:
- 路由器模式为
history
。
- 路径格式如下:
/
/single-level-pages
/two/level-pages
/two-levels-with/:param
/multiple/level/pages
/multiple/level/with/:param/
- 并非所有路径都共享
release-first
URL。 URL 我想首先发布的是 first-level-with/an-specific-param
.
- 我仔细检查了 RegExp(我也在那里使用了 console.log)。 CloudFront 中的重定向也运行良好。如果您在浏览器中输入不同的 URL,您会按预期从旧版服务器或 S3 获取内容。我在
beforeEach
导航守卫中使用的代码在暂存中也能正常工作,所以唯一的问题是当域相同时这还不够,因为 location.href
覆盖似乎没有强制当目的地在同一个域中时的新请求。
最后我是这样解决的:
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();
}
});
场景:
我有一个 Vue2 SPA 准备好替换遗留 LAMP 网站,但 PO 想逐步部署它(从一个 URL 开始)以测试用户的反应、分析、广告收入等
我们构建了这个架构来支持这种方法:
有效。因此,如果您转到 http://example.com/release-first(假设这是我们首先要公开发布的页面)CF returns 来自 S3 的内容,以及任何其他 URL 被提取来自旧服务器。
但是,当然,当您访问 /release-first
时,您处于 SPA 中,并且由于大部分导航都是使用 <router-link :to="">
完成的,您 被困 在 SPA 中,您可以访问新版本的其余部分,这是我们目前不需要的。
我认为可能的解决方案:
一种解决方案是用标准 <a>
链接替换所有 <router-link>
标签,这将强制浏览器每次都向 CloudFront 执行新的请求。这可能行得通,但我不想这样做,因为我必须更改很多链接,还因为链接不是用户移动的唯一方式(还有一些表单提交等)
所以,我尝试了类似的方法:
router.beforeEach((to, from, next) => {
if (!/\/release-first\/?$/.test(to.path)) {
window.location.href = `http://example.com${to.path}`
return;
} else {
next();
}
});
这在 staging
env 中工作正常(因为它有一个不同的子域,所以它重定向到生产)但是如果我在生产中尝试它不起作用。我不知道 Vue 是劫持了 Location API 还是什么,但它不会强制向 CloudFront 发出新的请愿书。
我也尝试过:
const absolutePath = `http://example.com${to.path}`;
window.history.pushState({ urlPath: absolutePath }, "", absolutePath);
window.location.reload();
但它也不起作用...而且我在 vue-router
的 Docs 中找不到强制页面在导航时重新加载的选项。关于如何实现这一目标的任何想法?
评论中要求的额外信息:
- 路由器模式为
history
。 - 路径格式如下:
/
/single-level-pages
/two/level-pages
/two-levels-with/:param
/multiple/level/pages
/multiple/level/with/:param/
- 并非所有路径都共享
release-first
URL。 URL 我想首先发布的是first-level-with/an-specific-param
. - 我仔细检查了 RegExp(我也在那里使用了 console.log)。 CloudFront 中的重定向也运行良好。如果您在浏览器中输入不同的 URL,您会按预期从旧版服务器或 S3 获取内容。我在
beforeEach
导航守卫中使用的代码在暂存中也能正常工作,所以唯一的问题是当域相同时这还不够,因为location.href
覆盖似乎没有强制当目的地在同一个域中时的新请求。
最后我是这样解决的:
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();
}
});