为何动态加载的JavaScript总是最后执行?
问题原因
你设置了script.async = false,但动态加载的脚本仍在页面静态JS之后执行,核心原因是你把动态脚本追加到了document.head的末尾。浏览器脚本执行的逻辑是:
- HTML中直接编写的静态
<script>会按DOM中的出现顺序依次执行(默认阻塞页面解析)。 - 动态创建的脚本即便设置了
async=false,用appendChild加到head末尾时,执行顺序会排在所有已存在于head的静态脚本之后;如果静态脚本在body中,浏览器解析到这些静态脚本时也会优先执行,因为它们是更早被发现的资源。
解决方案
方案1:启用document.currentScript.after插入脚本
你注释掉的document.currentScript.after(script)就是最直接的解决方式。document.currentScript指向当前正在执行的脚本(也就是调用LoadScript的脚本文件),用after插入动态脚本,会让它紧跟当前执行脚本之后运行——只要你在静态脚本之前调用LoadScript,动态脚本就会先于静态脚本执行。
修改后的函数:
function LoadScript(href, integrity) { var script = document.createElement("script"); script.type = 'text/javascript'; script.src = href; script.async = false; if (integrity) { script.integrity = integrity; script.crossOrigin = "anonymous"; script.referrerPolicy = "no-referrer"; } // 替换appendChild为currentScript.after document.currentScript.after(script); }
注意:如果在异步回调、事件处理函数中调用LoadScript,document.currentScript可能为null,这种情况需要用其他方案。
方案2:插入到指定静态脚本的前面
如果你明确要让动态脚本优先于某个特定静态脚本执行,可以通过选择器定位该静态脚本,将动态脚本插在它前面:
function LoadScript(href, integrity, targetScriptSelector) { var script = document.createElement("script"); script.type = 'text/javascript'; script.src = href; script.async = false; if (integrity) { script.integrity = integrity; script.crossOrigin = "anonymous"; script.referrerPolicy = "no-referrer"; } if (targetScriptSelector) { const targetScript = document.querySelector(targetScriptSelector); if (targetScript) { targetScript.before(script); return; } } // 找不到目标脚本时,回退到追加到head末尾 document.head.appendChild(script); } // 调用示例:优先于id为"static-main"的静态脚本执行 LoadScript('https://cdn.example.com/your-script.js', 'sha256-xxx', '#static-main');
方案3:修改静态脚本的加载属性
如果允许调整静态脚本的HTML代码,可以给静态脚本添加defer属性——带defer的静态脚本会在DOM解析完成后执行,而你的动态脚本(async=false)会在添加后立即执行,自然会排在静态脚本前面:
<!-- 给静态脚本添加defer --> <script src="./static-script.js" defer></script>
内容的提问来源于stack exchange,提问作者s k
相关产品推荐
相关产品推荐

