【116】vue-router使用懒加载机制,在生产环境中,如何避免浏览器缓存Webpack 3 编译后生成的js路径,导致404错误。(二)

8 篇文章 0 订阅
5 篇文章 0 订阅

整理思路

我在【115】vue-router使用懒加载机制,在生产环境中,如何避免浏览器缓存Webpack 3 编译后生成的js路径,导致404错误。(一) 一文中已经详细阐述了问题产生的原因和重现的方法。一共有两种解决方法。这篇文章准备详细解说一下第一种解决方法。第二种方法在文章总结处有提到。

要解决这个问题,F5 刷新是最好的解决办法。但是每次发布新版本后,都要求用户主动按 F5 刷新浏览器,会让用户觉得不方便。这对于快速迭代的产品来说尤其突出。

所以为了方便用户使用,我们希望当前端页面修改之后,系统能够自动刷新页面。

现在来整理一下思路:

一、既然浏览器缓存旧 js 文件名导致抛出 404 错误,那么就要捕获这个异常。

二、捕获异常之后,要监测一下客户端的版本是否低于服务器(如 Nginx )中的版本。如果是客户端版本低造成的,自动 F5 刷新;如果是其他原因,在控制台打印出错误信息。

三、注意在自动刷新的时候,不能使用 window.location.reload() 函数刷新。因为当浏览器抛出载入页面错误的时候,地址栏还没有更新地址。如果你利用给 window.location.href 赋值的方式刷新页面,那么这个地址会被前端路由拦截到。所以有效的办法是让浏览器先跳转到另外一个域名,再跳转回来。

源代码

我的所有博客的源代码都放在码云上,网址是https://gitee.com/zhangchao19890805/csdnBlog 。这篇博客的代码在git项目中的 blog116文件夹里面。公分为两个项目 blog116redirect 是负责跳转的;blog116main 是主要业务项目。

解决方案

第一步,要捕获出错的异常。这是在 vue-router 懒加载的时候出现的。vue-router 实际上是使用了 Webpack 代码分割的 api。为了方便的捕获异常,我使用了 Webpack 3 新加的 import(“./your/path”) 函数来加载 .vue 文件。Webpack 3 的 import 函数会返回 Promise,因此我在 import 函数后面加上 .catch(...) 函数就可以捕获异常。vue-router 配置文件内容如下:

import index from './index.vue';
import routerUtils from "./routerUtils.js";

export default [
    {
        path:'/',
        name: "index",
        component:index,
        children: [
            {
                path:"home",
                name: "home",
                component: ()=>import("./home.vue").catch(routerUtils.catchImport)
            },
            {
                path: "page1",
                name: "page1",
                component: ()=>import("./page1.vue").catch(routerUtils.catchImport)
            }
        ]
    }
]

第二步,捕获异常之后,要监测一下客户端的版本是否低于服务器(如 Nginx )中的版本。如果是客户端版本低造成的,自动 F5 刷新;如果是其他原因,在控制台打印出错误信息。

因为是在浏览器地址改变之前出错,所以每次前端路由跳转的时候需要Vuex记录下URL,代码如下:

router.beforeEach((to, from, next) => {
    // 记录要跳转过去的路径,如果载入页面失败,就刷新浏览器。
    store.dispatch("routerToPathAction", to.fullPath);
    next();
});

统一处理异常的代码如下:

import store from "./vuex/store.js"
import axios from "axios";
import localVersion from "./routerVersion.js";

const SITE_URL = "http://localhost";
const REDIRECT_SITE = "http://localhost:8081";

export default {
    async catchImport(err){
        try {
            // 发请求检查版本
            let res = await axios.get(SITE_URL + "/version.json", {
                params:{r: Math.random()}
            });
            if (localVersion < res.data.data.version) {
                window.location.href = REDIRECT_SITE + "/r?p=" + encodeURI(store.getters.routerToPath);
            } else {
                console.error("err", err);
            }
        } catch (err2) {
            console.error("err2", err2);
        }
    }
}

第三步、注意在自动刷新的时候,不能使用 window.location.reload() 函数刷新。因为当浏览器抛出载入页面错误的时候,地址栏还没有更新地址。如果你利用给 window.location.href 赋值的方式刷新页面,那么这个地址会被前端路由拦截到。所以有效的办法是让浏览器先跳转到另外一个域名,再跳转回来。

需要新建一个前端vue项目,这个项目对应我的码云中的 blog116/blog116redirect 。下面展示关键代码 。

router.js

import index from './index.vue';
import redirectVue from "./redirectVue.vue";
export default [
    {
        path:'/',
        name: "index",
        component:index,
        children: [
            // redirect
            {
                path: 'r',
                name: 'redirect',
                component: redirectVue
            }
        ]
    }
]

redirectVue.vue

<template>
    <div>正在跳转...</div>
</template>
<script>
    export default {
        data(){
            return{};
        },

        mounted(){
            let redirectUrl = this.$route.query.p;
            let url = decodeURI(redirectUrl);
            window.location.href = "http://localhost" + url;
        }
    }
</script>
<style lang="scss" rel="stylesheet/scss" scoped>   
</style>

总结第一种方法

这种解决方案有优点和缺点。

优点是,相对第二种解决方法(本文后面有讨论),可以大大减少浏览器发起的请求数量,缓解服务器压力。

缺点也很明显,浏览器必须等到抛出异常的时候才会更新前端页面,有可能更新不及时。而且如果浏览器缓存了更新前的页面,当浏览器再次进入同一个页面的时候,有可能不会抛出异常,而是继续运行缓存了的旧代码。

第二种方法:

简单的说,就是在路由改变的时候,加一个总的路由守卫,只要路由有变化,就发送请求,检查本地版本和服务器版本是否一致。如果一致,放行。如果不一致,页面刷新。刷新方法和第一种一样,跳转到新的域名之后,再跳转回来。跳转代码同样是 blog116/blog116redirect 中的内容。

实际测试中发现这种方法运行效率太低。每当改变前端路由的时候都要发请求。当然也可能是我的系统路由嵌套比较多的关系。不推荐大家使用第二种方法。

我一个写了两篇文章来说明这个问题:

【115】vue-router使用懒加载机制,在生产环境中,如何避免浏览器缓存Webpack 3 编译后生成的js路径,导致404错误。(一)

【116】vue-router使用懒加载机制,在生产环境中,如何避免浏览器缓存Webpack 3 编译后生成的js路径,导致404错误。(二)

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值