1. 事故起因
某次生产环境中,系统功能无法使用,排查发现是项目中的某一个公共 JS 工具类加载失败导致。该公共 JS 工具类放在某个 CDN 节点上(多项目共享引入),由于 CDN 节点故障,导致加载失败,从而影响页面功能!

JS 文件加载失败是前端开发常见问题之一,找到问题根源后,可以通过代码层面的优化进行兜底。
2. 为什么会出现 JS 加载失败?
为什么会出现 JS 加载失败?
由于网络请求具有不确定性,特别是在移动端和弱网环境下,JS 文件加载可能因以下原因失败:
- 网络问题:用户的网络环境不稳定
- CDN 故障:CDN 节点挂了,资源就直接 404
- 缓存污染:某些浏览器或代理缓存了错误的文件
以上这些问题不可完全避免,但我们能在代码层面进一步完善尽量给用户进行兜底。
3. 解决思路
既然是加载失败,那么是否可以提供一种重试机制,当前端加载 JS 失败了进行重试,另外由于单节点的问题,我们还可以多源备份,避免单节点故障导致的问题!
- 自动重试:加载失败后,尝试再次发起请求
- 多源加载:比如主域名失败后,切换备用的 CDN 地址
4. 基础监听与重试方案
核心逻辑是:用 script 标签去加载资源,监听 onerror 事件,失败后重试,以下是加载重试的代码,开发者可根据实际需求调整参数:
function loadScript(url, options = {}) {
const { maxRetry = 3, timeout = 5000 } = options;
let attempt = 0;
return new Promise((resolve, reject) => {
const load = () => {
attempt++;
const script = document.createElement("script");
script.src = url + (url.includes("?") ? "&" : "?") + "retry=" + attempt;
script.async = true;
let timer = setTimeout(() => {
script.remove();
if (attempt < maxRetry) {
console.warn(`加载超时,正在重试 ${attempt}/${maxRetry} ...`);
load();
} else {
reject(new Error(`加载超时:${url}`));
}
}, timeout);
script.onload = () => {
clearTimeout(timer);
resolve();
};
script.onerror = () => {
clearTimeout(timer);
script.remove();
if (attempt < maxRetry) {
console.warn(`加载失败,正在重试 ${attempt}/${maxRetry} ...`);
load();
} else {
reject(new Error(`加载失败:${url}`));
}
};
document.head.appendChild(script);
};
load();
});
}
使用方式
loadScript("https://cdn.yourname.com/app.js", { maxRetry: 3, timeout: 3000 })
.then(() => {
console.log("脚本加载成功");
})
.catch((err) => {
console.error("脚本加载最终失败:", err);
// 加载重试依旧失败可以提示用户,比如提示用户刷新
// alert('资源加载失败,请重新刷新页面')
});
5. 多源备份加载
为避免单节点故障,可以准备多个地址:
const cdnList = [
"https://cdn1.yourname.com/app.js",
"https://cdn2.yourname.com/app.js",
"https://cdn3.yourname.com/app.js"
];
(async () => {
for (const url of cdnList) {
try {
await loadScript(url);
console.log("成功加载:", url);
break;
} catch (e) {
console.warn("失败,尝试下一个源:", url);
}
}
})();
这样,即使某个 CDN 节点彻底挂了,也能通过备用源恢复。
6. 总结
通过本文的介绍,主要解决以下几个问题:
加载失败的重试:失败重试,次数通常 2 - 3 次足够,过多重试会影响用户体验 CDN 容灾:准备多个 CDN 地址,主地址失败时自动切换 提供降级方案:关键资源重试加载依然失败时显示友好提示(比如演示代码中弹出警告框告知刷新)
通过 JS 加载重试机制可以提升我们应用的可靠性,即便因为各种原因出现加载失败的问题,都尽可能给用户进行兜底。

