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

问题点
-
什么时间重试?
在script加载事件出错的时候进行事件拦截处理
-
如何重试?
通过全局Err事件监听,然后根据script加载出错处理
- 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 代码),并将其插入到文档流中。
- 应用场景:动态生成页面内容、注入脚本、测试调试等。
注意事项
- 页面加载期间使用:仅在页面加载过程中有效,若在文档加载完成后使用会导致整个页面内容被清空。
- 阻塞解析:同步操作会阻塞页面解析,不建议用于异步加载或页面加载完成后。
- 内容覆盖:会覆盖原有内容,需谨慎使用以避免意外覆盖重要信息。