脚本加载失败重试机制

概述

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

注意事项

  • ‌页面加载期间使用‌:仅在页面加载过程中有效,若在文档加载完成后使用会导致整个页面内容被清空。 ‌
  • ‌阻塞解析‌:同步操作会阻塞页面解析,不建议用于异步加载或页面加载完成后。 ‌
  • ‌内容覆盖‌:会覆盖原有内容,需谨慎使用以避免意外覆盖重要信息。 ‌
相关推荐
小万7423 分钟前
God‘s Eye View 深度解析:15 路公开信号 + CesiumJS 的浏览器级 OSINT 控制台,60 帧渲染的“真实间谍卫星模拟器”
前端
IT星宿9 分钟前
浏览器标签页全是一个图标:我用名字哈希生成 favicon,让每个项目都有身份标识
前端
OpsEye18 分钟前
大模型账单对账难:不同厂商 Token 统计口径差异怎么处理
javascript·ai编程
全栈项目管理程序猿19 分钟前
ArcGIS JS 基础教程(32):体元系列 - VoxelSlice 体元切片
前端·javascript
拖孩2 小时前
AI 帮我写的小程序「厨菜记」上线满月了,挣了两百块!!!
前端·后端·微信小程序
用户360055579002 小时前
Kestrel_VLLM - 13 · 为什么排除 MoE FFN Tiling 与 Tensor Core
前端
Hilaku3 小时前
AI 流式输出都用 SSE,什么时候必须换 WebSocket?
前端·javascript·程序员
奇牙coding3 小时前
Codex CLI 升级后多文件编辑静默失效:config.yaml 枚举变更排查与修复指南
java·前端·javascript·ai
小羊没烦恼!3 小时前
Ajax与JSON的一些总结
android·java·前端·数据库·mysql·算法·okhttp
程序员老赵3 小时前
Docker 部署 Filestash:轻松搭建浏览器文件管理平台
前端·docker·开源