脚本加载失败重试机制

概述

前端脚本资源加载的时候可能会出错,特别是cdn资源,因此我们可以写一个js资源加载失败的重试机制,根据备用域名依次加载资源,最大程度提高用户体验。

效果

问题点

  1. 什么时间重试?

    在script加载事件出错的时候进行事件拦截处理

  2. 如何重试?

通过全局Err事件监听,然后根据script加载出错处理

  1. script插入方式?

通过document.write(会阻塞页面保证脚本顺序)插入最新的脚本请求到页面,注意:如果js加载过程中,严格区分前后加载顺序就不能动态创建script的形式重试

实现

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <script>


        const backupsDomain = [
            "https://cdn.bootcdn.newt",
            "https://cdnjs.cloudflare.com",
            "https://cdn.bootcdn.net",
        ]


        const nextDomain = {}

        window.addEventListener("error", (e) => {
            if (e.target.tagName === "SCRIPT") {
                const target = new URL(e.target.src)
                const pathName = target.pathname
                if (nextDomain[pathName] >= backupsDomain.length) {
                    console.log("所有域名均不可用")
                    return
                }
                if (!nextDomain[pathName]) {
                    nextDomain[pathName] = 0
                }
                const index = nextDomain[pathName]
                const domain = backupsDomain[index]
                const newUrl = new URL(domain + target.pathname + target.search);

                console.log("target", newUrl)
                // 方式1(不区分顺序可以用这种)
                const script = document.createElement("script")
                script.src = newUrl.toString()
                // e.target.parentElement.insertBefore(script, e.target)
                // 方式2(严格按照页面js脚本引入顺序加载)
                document.write(`\<script src="${newUrl.toString()}"><\/script>`)
                e.target.remove()
                nextDomain[pathName]++

            }
        }, true)
    </script>
</head>

<body>
    <script src="https://cdn.bootcdn.net1/ajax/libs/vue/3.5.20/vue.global.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/socket.io/4.8.1/socket.io.min.js"></script>

    <div id="app"></div>
    <script>
        console.log("结束", Vue)

        Vue.createApp({
            data() {
                return {
                    message: 'Hello Vue!',
                    count: 0
                }

            },
            methods: {
                test() {
                    console.log("test")
                    this.count++
                    this.message = 'Button clicked ' + this.count + ' times.'
                }
            },
            template: `<div @click="test">{{ message }}</div>`
        }).mount('#app')
    </script>

</body>

</html>

注意

document.write() 是 JavaScript 中用于向文档写入内容的方法,支持插入文本、HTML 标签或 JavaScript 代码。以下是其核心要点及使用场景:

核心功能

  • 写入内容‌:接受字符串参数(如文本、HTML 或 JavaScript 代码),并将其插入到文档流中。 ‌
  • 应用场景‌:动态生成页面内容、注入脚本、测试调试等。 ‌

注意事项

  • 页面加载期间使用‌:仅在页面加载过程中有效,若在文档加载完成后使用会导致整个页面内容被清空。 ‌
  • 阻塞解析‌:同步操作会阻塞页面解析,不建议用于异步加载或页面加载完成后。 ‌
  • 内容覆盖‌:会覆盖原有内容,需谨慎使用以避免意外覆盖重要信息。 ‌
相关推荐
前端付豪1 分钟前
万事从 todolist 开始
前端·vue.js·前端框架
小胖霞1 分钟前
从零开始:在阿里云 Ubuntu 服务器部署 Node+Express 接口(基于公司 GitLab)
前端·后端
A_Bin4 分钟前
前端工程化之【包管理器】
前端
小肚肚肚肚肚哦5 分钟前
CSS 伪类函数 :where 简介
前端·css
Nick56837 分钟前
Swift -- 第三方登录之微信登录 源码分享
前端
麦麦大数据14 分钟前
D026 vue3+django 论文知识图谱推荐可视化系统 | vue3+vite前端|neo4j 图数据库
前端·django·vue3·知识图谱·推荐算法·论文文献·科研图谱
小肚肚肚肚肚哦21 分钟前
伪元素与普通元素的层级关系问题浅析
前端·css
梦想CAD控件1 小时前
网页CAD中组(Group)功能的二次开发
前端·javascript·github
讨厌吃蛋黄酥1 小时前
🔥 JavaScript异步之谜:单线程如何实现“同时”做多件事?99%的人都理解错了!
前端·javascript·面试
华仔啊1 小时前
别再纠结Pinia和Vuex了!一篇文章彻底搞懂区别与选择
前端·vue.js