前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Web性能】Javascript 代码性能优化条目(一)

【Web性能】Javascript 代码性能优化条目(一)

作者头像
前端修罗场
发布2022-07-29 07:56:06
5110
发布2022-07-29 07:56:06
举报
文章被收录于专栏:Web 技术

初学者,特别是自学的孩子,在学习的过程中常会遇到各种各样的瓶颈,例如:如何写好javascript、要注意什么等等。这篇文章中,总结了过去javascript一些高效的写法,供大家参考。


脚本

1 脚本数量

每个<script>标签初始下载时都会阻塞页面渲染,减少页面包含的<script>标签数量有助于改善这一情况。同时,不仅是针对外链脚本,内嵌脚本的数量同样也要限制。浏览器在解析HTML页面的过程中每遇到一个script标签,都会因执行脚本而导致一定的延时,因此最小化延迟时间将会明显改善页面的总体性能。

考虑到HTTP请求会带来额外的性能开销,因此下载单个100KB的文件将比下载4个25KB的文件更快。所以,减少页面中外链脚本文件的数量将会改善性能。


无阻塞脚本

减少JS文件大小并限制HTTP请求数仅仅是创建响应迅速的Web应用的第一步。尽管下载单个较大的JS文件只会产生一次HTTP请求,但这么做会锁死浏览器一大段时间。因此,避免这种情况,你需要向页面中逐步加载JS文件。

无阻塞脚本的好处在于页面加载完成后才会加载JS代码。即,在window.load事件触发后才会下载脚本。

2 延迟脚本

HTML4中引入一个script标签扩展属性:defer。该属性指明元素所含的脚本不会修改DOM,代码能安全地延迟执行。

同时,HTML5中引入async属性,用于异步加载脚本。async与defer的相同点是采用并行下载,在下载过程中不会产生阻塞。区别在于执行时机,async是加载完成后自动执行,defer需要等待页面完成后执行。

3 动态加载脚本

如下:

代码语言:javascript
复制
let script = document.createElement("script");
script.src = "1.js";
document.head.appendChild(script);

这个新建的script元素加载了1.js文件。文件在该元素被添加到页面时开始下载。这种方式的重点在于:无论何时启动下载,文件的下载和执行过程不会阻塞页面其他进程。甚至,你可以将代码插入到<head>区域而不会影响页面其他部分。因为,一般而言,把新建的<script>标签添加到<head>标签里比添加到<body>里保险,尤其是在页面加载过程中执行代码时更是如此。当<body>中的内容没有全部加载完成,IE可能会抛出一个“操作已终止”的错误信息。

使用动态脚本加载文件,返回的代码通常会立即执行。但是,当代码只包含供页面其他脚本调用的接口时,就会出问题。在这种情况下,你必须跟踪并确保脚本下载完成且准备就绪:

<script>元素接收完成时会触发一个load事件。你可以通过监听该事件来获得脚本加载完成时的状态:

代码语言:javascript
复制
let script = document.createElement("script");
script.onload = function() {
  console.log("script loaded!");
}
script.src = "1.js";
document.head.appendChild(script);

而IE支持另一种实现方式,它会触发一个readystatechange事件,script元素提供一个readyState属性,它的值在外链文件的下载过程的不同阶段会发生变化,其取值如下:

  • “uninitialized”:初始状态
  • “loading”:开始下载
  • “loaded”: 下载完成(关注)
  • “interactive”: 所有数据已准备就绪(关注)

实际中,最有用的两个状态是"loaded"和"complate"。IE下,readyState的值并不一致,有事到达loaded状态不会到达complate;有时甚至不经过loaded就到达complate。所以,最保障的方式是对两种状态同时检查,只要有一个触发,就移除readystatechange事件处理器。下面,我们把这个过程放在一个函数中处理:

代码语言:javascript
复制
function loadScript(url,callback) {
    let script = document.createElement("script");
    if(script.readyState) {
      script.onreadystatechange = function() {//IE
        if(script.readyState == "loaded" || script.readyState == "complate") {
          script.onreadystatechange = null;//移除`readystatechange`事件处理器
          callback();
        }else {//其他浏览器
          script.onload = function() {
            callback();
          }
        }
        script.src = url;
        document.head.appendChild(script);
      }


    }
  }

如果需要的话,你可以动态加载尽可能多的JS文件到页面。但是:要考虑清楚文件的加载顺序。在所有主流浏览器中,只有Firefox和Opera能保证脚本会按照你指定的顺序执行,其他浏览器将会按照从服务器返回的顺序下载和执行代码。

对于多个文件,更好的做法还是把它们合并为一个文件。

4 XHR脚本注入

XHR脚本注入是另一种无阻塞脚本加载方法。

代码语言:javascript
复制
let xhr = new XMLHttpRequest();
  xhr.open("get","1.js",true);
  xhr.onreadystatechange = function() {
    if(xhr.readyState === 4) {
      if(xhr.status => 200 && xhr.status < 300 || xhr.status === 304) {
        let script = document.createElement("script");
        script.text = xhr.responseText;
        document.head.appendChild(script);
      }
    }
  }

优点:你可以下载JS代码但不立即执行。由于代码是在script标签之外返回的,因此它下载后不会自动执行,这使得你可以把脚本的执行 推迟到你准备好的时候。

  • 优点:在主流浏览器中能工作,不存在兼容性问题
  • 缺点:xhr不支持跨域。

大型Web应用通常不会采用XHR脚本注入方式。

本篇对javascript脚本优化的介绍先暂时到这里,下一篇中我们将从作用域方面继续介绍。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-06-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端修罗场 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 无阻塞脚本
    • 2 延迟脚本
      • 3 动态加载脚本
        • 4 XHR脚本注入
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档