无body闭合标签编辑权限时如何在其前插入脚本
解决方案
仅拥有页面<head>区块编辑权限时,完全可以通过原生JavaScript将目标脚本实际插入到</body>标签之前的位置,无需操作body闭合标签处的源码。
你之前的defer方案失效原因
带defer属性的脚本仅会将执行时机延后到DOM树解析完成后,脚本标签本身在DOM树中的位置仍然是你插入的head区域,如果你的目标脚本存在自身位置校验、依赖DOM插入顺序的逻辑,就会出现不生效的问题。部分第三方建站工具也会自动改写head区域带defer/async属性的外链标签,导致加载逻辑异常。
可直接复用的实现代码
把下面这段内联脚本放到你有权限编辑的head区域即可,它会在DOM就绪后自动把目标脚本插入到body的最末尾,和手动把脚本写在</body>前的效果完全一致:
<script> function injectScriptToBodyEnd() { if (!document.body) { setTimeout(injectScriptToBodyEnd, 1); return; } const script = document.createElement('script'); // 替换为你的目标脚本地址 script.src = 'demo_defer.js'; // 如果需要脚本加载完成后执行逻辑,可在这里添加onload回调 // script.onload = function() { // 自定义逻辑 } document.body.appendChild(script); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', injectScriptToBodyEnd); } else { injectScriptToBodyEnd(); } </script>
方案特性
- 插入后脚本标签的实际DOM位置就是body的最后一个子节点,和手写在
</body>前的DOM结构无差异,能通过各类脚本的位置校验 - 插入时机为DOM树构建完成后,不会阻塞页面渲染,加载时机和原生写在body末尾的脚本一致
- 兼容所有主流浏览器,不存在API兼容问题
- 如果需要插入内联脚本而非外链脚本,只需将
script.src = 'xxx'替换为script.textContent = '你要执行的JS代码'即可
注意:不要在head区域未做DOM就绪检测就直接调用
document.body.appendChild,此时DOM还未解析到body节点,会直接抛出报错。
内容的提问来源于stack exchange,提问作者Dan
相关产品推荐
相关产品推荐

