摘要:的堵塞特性上面引用两段话的意思大致是,当浏览器解析文档时,一旦遇到标签没有和属性就会立即下载并执行,与此同时浏览器对文档的解析将会停止,直到代码执行完成。实现代码执行代码缺点是不能跨域请求参考装载和执行元素所著的的第一章
Script 的堵塞(block)特性
Scripts without async or defer attributes, as well as inline scripts, are fetched and executed immediately, before the browser continues to parse the page. - MDN
the blocking nature of JavaScript, which is to say that nothing else can happen while JavaScript code is being executed. In fact, most browsers use a single process for both user interface (UI) updates and JavaScript execution, so only one can happen at any given moment in time. The longer JavaScript takes to execute, the longer it takes before the browser is free to respond to user input. - Nicholas C. Zakas「High Performance JavaScript 」
上面引用两段话的意思大致是,当浏览器解析DOM文档时,一旦遇到 script 标签(没有defer 和 async 属性)就会立即下载并执行,与此同时浏览器对文档的解析将会停止,直到 script 代码执行完成。出现这种堵塞行为一方面是因为浏览器的UI渲染,交互行为等都是单线程操作,另一方是因为 script 里面的代码可能会影响到后面文档的解析,比如下面的代码:
html
这个堵塞特性会严重的影响用户体验,下面是几种优化方案:
尽量把脚本往文档的后面放,以减少对文档的堵塞,最好放在
前面。
尽量把脚本按照它们的依赖关系放在一个文件中
不过更好的方法是下面的非堵塞加载脚本(Nonblocking Scripts)的方法:
1. Deferred Script (延迟脚本)Script 有一个 defer 属性,拥有这个属性的script表明这个script不会修改DOM,因此这段脚本会在文档树全部解析完成后触发( to be executed after the document has been parsed). 但这个属性并不被所有的浏览器支持。
2. Dynamic Script Elements (动态脚本)原理就是使用脚本创建 script 元素,设置 src 需为要动态添加脚本的 URL,再把这个 script 添加到DOM中。有时我们需要动态脚本加载完成后再执行某些操作,这就需要我们在脚本加载完成后添加一个回调函数,这个可以通过 script 的 onload 事件实现。下面的实现代码:
jsfunction loadJS(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{ script.onload = function(){ callback(); } } script.src = url; document.getElementsByTagName("head")[0].appendChild(script); }
有时我们需要我们动态加载的脚本按照我们加载的顺序执行,但上面的实现并不能保证这一点,加载的脚本在下载完成后就会立即执行,而不会按照我们定义的顺序。要解决这个问题也不难,可以参照下面的代码:
jsloadJS("a.js", function(){ loadJS("b.js", function(){ loadJS("c.js", function(){ app.init(); }) }) })
当有大量的脚本需要动态添加时,这样写也会遇到问题;另外的解决方案是利用一些现成的库,比如 LABjs
3. XMLHttpRequest Script Injection (XHR动态插入)原理是利用XMLHttpReques(XHR)对象,动态获取一段JS代码,然后插入文档。
相对其他方法来说的一个优点是可以“懒执行”,也就是JS代码已经先下载好了并没有执行,可以在需要的来执行(?)(之前的动态脚本在下载后会立即执行)。实现代码:
jsfunction xhrLoadJS (url, callback){ var xhr = new XMLHttpRequest(); xhr.open("get", url, true); xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){ var script = document.createElement("script"); script.type = "text/script"; script.text = xhr.responseText; eval(xhr.responseText); // 执行代码 document.body.appendChild(script); callback(); } } } xhr.send(null); }
缺点是不能跨域请求
参考Javascript 装载和执行
MDN Script元素
Nicholas C. Zakas 所著的「High Performance JavaScript 」的第一章 "Loading and Execution"
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/85720.html
摘要:是一款可爱的小插件,将和浏览器的封装到一起,解决了单纯使用进行无刷新加载时对搜索引擎的不友好,并且节省了开支提高了浏览速度,明显地优化了用户体验。是提供的,是对浏览器历史对象的增强。 showImg(https://segmentfault.com/img/remote/1460000007640529?w=1008&h=569); pjax 是一款可爱的 jQuery 小插件,将 a...
摘要:是一款可爱的小插件,将和浏览器的封装到一起,解决了单纯使用进行无刷新加载时对搜索引擎的不友好,并且节省了开支提高了浏览速度,明显地优化了用户体验。是提供的,是对浏览器历史对象的增强。 showImg(https://segmentfault.com/img/remote/1460000007640529?w=1008&h=569); pjax 是一款可爱的 jQuery 小插件,将 a...
摘要:我把这个领域的东西写成了一个系列,以后还会继续完善下去安全一同源策略与跨域安全二攻击安全三攻击 上文说完了CSRF攻击,本文继续研究它的兄弟XSS攻击。 什么是XSS攻击 XSS攻击全名(Cross-Site-Script)跨域脚本攻击,为了跟CSS(Cascading-Style-Sheet)区分开来,所以缩写是XSS。 XSS攻击的原理 上一节说道的CSRF攻击是利用的是伪请求,这...
摘要:我把这个领域的东西写成了一个系列,以后还会继续完善下去安全一同源策略与跨域安全二攻击安全三攻击 上文说完了CSRF攻击,本文继续研究它的兄弟XSS攻击。 什么是XSS攻击 XSS攻击全名(Cross-Site-Script)跨域脚本攻击,为了跟CSS(Cascading-Style-Sheet)区分开来,所以缩写是XSS。 XSS攻击的原理 上一节说道的CSRF攻击是利用的是伪请求,这...
摘要:关于动静分离的描述,这里推荐一篇不错的博文网站静态化处理动静分离策略。这里的解决办法则是采用的属性,将其应用于数据请求相关的上,就可以达到脚本与数据并发加载的效果。 作者:莫冠钊 转载请注明出处,保留原文链接和作者信息 前言 当今许多大型网页应用尤其是SPA均采用了动静分离的策略。关于动静分离的描述,这里推荐一篇不错的博文 网站静态化处理—动静分离策略。 本人是做前端的,之前有幸与一...
阅读 130107·2024-02-01 10:43
阅读 764·2024-01-31 14:58
阅读 744·2024-01-31 14:54
阅读 82544·2024-01-29 17:11
阅读 2831·2024-01-25 14:55
阅读 1901·2023-06-02 13:36
阅读 2784·2023-05-23 10:26
阅读 843·2023-05-23 10:25