脚本加载失败重试机制

概述

前端脚本资源加载的时候可能会出错,特别是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 代码),并将其插入到文档流中。 ‌
  • 应用场景‌:动态生成页面内容、注入脚本、测试调试等。 ‌

注意事项

  • 页面加载期间使用‌:仅在页面加载过程中有效,若在文档加载完成后使用会导致整个页面内容被清空。 ‌
  • 阻塞解析‌:同步操作会阻塞页面解析,不建议用于异步加载或页面加载完成后。 ‌
  • 内容覆盖‌:会覆盖原有内容,需谨慎使用以避免意外覆盖重要信息。 ‌
相关推荐
Lee川3 小时前
Milvus 实战:当 RAG 遇上向量数据库,从"玩具 Demo"到"生产可用的"那一步
前端·数据库·人工智能
anOnion4 小时前
构建无障碍组件之Toolbar Pattern
前端·html·交互设计
惊鸿一博4 小时前
图标加载方式_zeroIcon_是否加前缀mdi
开发语言·前端·javascript
2501_940041744 小时前
前端工程化进阶:5个高交互与可视化项目提示词
前端
你很易烊千玺4 小时前
JS 异步 从零讲(大白话 + 真实场景 + 可运行案例)
前端·javascript·vue.js
华洛6 小时前
讲讲如何在传统产品中挖掘AI需求
javascript·产品经理·产品
why技术6 小时前
AI Coding开始进入第四个时代,我还没上车呢!
前端·人工智能·后端
大家的林语冰7 小时前
CSS 已死?DOM 性能黑洞!Pretext 排版革命让你在文本间跳舞,没有 DOM 也能纵享丝滑~
前端·javascript·css
vipbic7 小时前
我也该升级了,陪伴了我7年的博客
前端
Lee川7 小时前
RAG 实战:从一篇掘金文章出发,拆解检索增强生成的全链路
前端·人工智能·后端