脚本位置
- 脚本会阻塞页面谊染
- 浏览器在解析到<body>标签之前,不会渲染页面的任何
部分。 把脚本放到页面顶部将会导致明显的延迟 - 推荐将所有的句口ipt>标签尽可能放到<body>标签的底部,以尽量减少对整个页面下载的影响
组织脚本
- 控制脚本数量
<script>标签初始下载时都会阻塞页面植染, 所以减少页面包含的<script>标签数量有助于改善这一情况。内嵌脚本的数量同样也要限制。
无阻塞的脚本
JavaScript倾向于阻止浏览器的某些处理过程,如HTTP请求和用户界面更新,这是开发者所面临的最显著的性能问题。减少JavaScript文件大小并限制HTTP请求数仅仅是创建响应迅速的Web应用的第一步。Web应用的功能越丰富,所需要的JavaScript代码就越多,所以精简源代码并不总是可行。尽管下载单个较大的JavaScript文件只产生一次HTTP请求, 却会锁死浏览器一大段时间。为避免这种情况,你需要向页面中逐步加载JavaScript文件, 这样做在某种程度上来说不会阻塞浏览器。
无阻塞脚本的秘诀在干,在页面加载完成后才加载JavaScript代码。用专业术语来说,这意味着在window对象的load事件触发后再下载脚本。有多种方式可以实现这一效果。
延迟的脚本
HTML 4为<script>标签定义了一个扩展属’性:defer0Defer属性指明本元素所含的脚本不会修改DOM,因此代码能安全地延迟执行。
带有defer属性的<script>标签可以放置在文档的任何位置。对应的JavaScripr文件将在页面解析到<script>标签时开始下载,但并不会执行,直到DOM加载完成(onload事件被触发前)。当一个带有defer属性的JavaScripr文件下载肘,它不会阻塞浏览器的其他进程,因此这类文件可以与页面中的其他资源并行下载。
任何带有defer属性的<script>元素在DOM完成加载之前都不会被执行,无论内嵌或外链脚本都是如此。
动态脚本元素
var script= document.createElement("script")
script.type="text/javascript"
script.src ="filel.js"
document.getElementsByTagName(head")[0].appendChild(script)
这 种技术的重点在于:无论在何时启动下载,文件的下载和执行过程不会阻塞页面其他进程。 你甚至可以将代码放到页面<head>区域而不会影响页面其他部分(用于下载i主文件的HTTP链接本身的影响除外)。
XMLHttpRequest脚本注入
function loadScript(url){
let 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){
let script = document.createElement('script')
script.type = 'text/javascript'
script.text = xhr.responseText
document.body.appendChild(script)
}
}
}
xhr.send(null)
}
- 优点
- 可以下载JavaScript 代码但不立即执行
- 同样的代码在所有主流浏览器中无一 例外都能正常工作
- 局限性
- JavaScript文件必须与所请求的页面处干相同的域
推荐的无阻塞模式
只需两步:先添加动态加载所需的代码,然后加载初始化页面所需的剩下的代码。因为第一部分的代码尽量精简,甚至可能只包含loadScript() 函数, 它下载执行都很快, 所以不会对页面有太多影响。 一旦初始代码就位, 就用它来加载剩余的JavaScript。 例如:
<script type="text/javascript”src=”loader.js”></script>
<script type="text/javascript">
loadScript("the-rest.js",function(){
Application.init();
})
</script>
把这段加载代码放到</body>闭合标签之前。
这样做有几个好处:
- 首先,如前文提到,应样做确保了JavaScript执行过程中不会阻碍页面其他内容的显示。
- 当第二个JavaScript 文件完成下载时,应用所需的所有DOM结构已经创建完毕,并做好了交互的准备,从而避免了需要另一个事件(比如window.onload)来检测页面是否准备好。
小结
管理浏览器中的JavaScript代码是个棘手的问题,因为代码执行过程会阻塞浏览器的其他进程,比如用户界面绘制。每次遇到<script>标签,页面都必须停下来等待代码下载(如果是外链文件)并执行,然后继续处理其他部分。尽管如此,还是有几种方法能减少JavaScript 对性能的影响:
- </body>闭合标签之前,将所有的<script>标签放到页面底部。这能确保在脚本执行前页面已经完成了渲染。
- 合并脚本。页面中的<script>标签越少,加载也就越快,响应也更迅速。无论外链文件 还是内嵌脚本都是如此。
- 有多种无阻塞下载JavaScript的方住:
- 使用<script>标签的defer属性:
- 使用动态创建的<script>元素来下载并执行代码:
- 使用XHR对象下载JavaScript代码井注入页面中。
通过以上策略,可以极大提高那些需要使用大量JavaScript的Web应用的实际性能。