JavaScript 性能优化:解决脚本阻塞与加载策略

山海之间
山海之间
发布时间:2026-10-14 | 4人浏览过
原创

JavaScript 脚本的执行会导致浏览器暂停页面解析,影响用户交互体验。通过合理放置脚本位置、合并代码以及利用 defer、async 或动态脚本加载等技术,可以有效减少阻塞,显著提升网页加载性能。

理解脚本阻塞原理

当浏览器在 HTML 文档中遇到 <script> 标签时,出于安全考虑(防止脚本修改 DOM 影响后续内容),它会停止解析剩余 HTML,转而下载并执行 JavaScript。这一过程会阻塞页面的渲染和其他资源(如 CSS、图片)的下载,导致用户看到空白页面,直到脚本执行完毕。

图 1 JavaScript 文件的加载和执行阻塞其他文件的下载

在传统做法中,开发者习惯在 <head> 中加载外部 JS 文件,这会严重延迟 <body> 内容的渲染。现代浏览器虽然允许并行下载多个 JS 文件,但 JS 本身仍会阻塞样式表和图片资源的下载。因此,优化脚本加载顺序和方式是提升性能的关键。

基础优化策略

第 1 步:调整脚本位置至页面底部

  • 目的:确保页面主要内容优先渲染,减少用户等待白屏的时间。
  • 操作:将所有 <script> 标签移动到 </body> 闭合标签之前。
  • 代码示例:
<html>
<head>
 <title>Source Example</title>
 <link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
 <p>Hello world!</p>
 
 <!-- 推荐的代码放置位置 -->
 <script type="text/javascript" src="script1.js"></script>
 <script type="text/javascript" src="script2.js"></script>
</body>
</html>

第 2 步:合并与减少脚本数量

  • 目的:减少 HTTP 请求开销及解析次数。
  • 操作:使用构建工具将多个 JS 文件合并为一个。避免在 <link> 标签后紧跟内嵌脚本,以防样式未加载完成时脚本读取样式信息出错。

高级:无阻塞加载技术

对于大型应用,仅靠放置位置和合并无法完全解决问题。以下技术可实现脚本在不阻塞主线程的情况下加载。

第 3 步:使用 defer 属性(同步加载,延迟执行)

  • 原理:脚本立即下载,但等到 DOM 树构建完成(window.onload 之前)才执行。不修改 DOM 时可安全使用。
  • 兼容性:IE 4+, Firefox 3.5+。不支持的浏览器会忽略该属性并可能引发阻塞。
<script type="text/javascript" src="script1.js" defer></script>

第 4 步:使用 async 属性(异步加载,立即执行)

  • 原理:HTML5 新增属性。脚本下载与页面解析并行,一旦下载完成立即执行。
  • 注意:执行顺序不确定,依赖关系的脚本不宜使用此方法。

第 5 步:动态创建 script 元素(跨浏览器推荐)

  • 原理:通过 JS 动态创建 <script> 节点并添加到文档,实现非阻塞下载。
  • 事件监听:
    • Firefox/Opera/Safari/Chrome: 监听 onload 事件。
    • IE: 监听 readystatechange 事件,检查 readyState 为 'loaded' 或 'complete'。

封装兼容函数如下:

function loadScript(url, callback){
 var script = document.createElement("script")
 script.type = "text/javascript";
 if (script.readyState){ //IE
  script.onreadystatechange = function(){
   if (script.readyState == "loaded" || script.readyState == "complete"){
    script.onreadystatechange = null;
    callback();
   }
  };
 } else { //Others
  script.onload = function(){
   callback();
  };
 }
 script.src = url;
 document.getElementsByTagName("head")[0].appendChild(script);
}

若需保证加载顺序,可递归调用:
loadScript("script1.js", function() { loadScript("script2.js", callback); });

第 6 步:使用 XMLHttpRequest (XHR) 注入

  • 原理:通过 XHR 获取 JS 文本,再创建动态 <script> 插入页面。适用于需要控制执行时机的场景。
  • 限制:通常受同源策略限制,难以从 CDN 加载代码。

总结

优化 JavaScript 加载性能的核心在于减少阻塞时间。建议优先遵循“脚本放底部”原则,并结合业务需求选择 defer、async 或动态脚本加载技术。对于有依赖关系的大型脚本,打包合并仍是最佳实践。

以上就是JavaScript性能优化总结之加载与执行的详细内容,更多关于JavaScript性能优化的资料请关注本站其它相关文章!

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表