把JavaScript文件放在文档的头部还是尾部
2018-03-09 16:03
537 查看
首发于:技术风暴
我们今天来聊一聊关于JavaScript文件的引入位置的问题;大家在平时的Web开发中有没有想过这样一个问题,那就是我应该在文档的头部(也就是
首先我们需要了解的一点就是,在浏览器渲染页面之前,它需要通过解析
还有一点是需要我们注意的,那就是外部引入的脚本(
看到这里,也许很多开发者都会想:既然把脚本(
![](https://dreamapple.me/2017/04/15/%E6%8A%8AJavaScript%E6%96%87%E4%BB%B6%E6%94%BE%E5%9C%A8%E6%96%87%E6%A1%A3%E7%9A%84%E5%A4%B4%E9%83%A8%E8%BF%98%E6%98%AF%E5%B0%BE%E9%83%A8/google.png)
我们可以看到,这个搜索页面在头部加载了5个JavaScript文件(箭头标注的地方),其中两个JavaScript文件是内联的(
![](https://dreamapple.me/2017/04/15/%E6%8A%8AJavaScript%E6%96%87%E4%BB%B6%E6%94%BE%E5%9C%A8%E6%96%87%E6%A1%A3%E7%9A%84%E5%A4%B4%E9%83%A8%E8%BF%98%E6%98%AF%E5%B0%BE%E9%83%A8/baidu.png)
baidu搜索页在head中引入的JavaScript
我们可以看到,百度也在头部引入了一些JavaScript文件,这些文件引入的方式与Google的做法差不多,都在引入外部资源的
![](https://dreamapple.me/2017/04/15/%E6%8A%8AJavaScript%E6%96%87%E4%BB%B6%E6%94%BE%E5%9C%A8%E6%96%87%E6%A1%A3%E7%9A%84%E5%A4%B4%E9%83%A8%E8%BF%98%E6%98%AF%E5%B0%BE%E9%83%A8/stackoverflow.png)
stackoverflow首页在head中引入的JavaScript
![](https://dreamapple.me/2017/04/15/%E6%8A%8AJavaScript%E6%96%87%E4%BB%B6%E6%94%BE%E5%9C%A8%E6%96%87%E6%A1%A3%E7%9A%84%E5%A4%B4%E9%83%A8%E8%BF%98%E6%98%AF%E5%B0%BE%E9%83%A8/weibo.png)
weibo首页在head中引入的JavaScript
最后一个是facebook的首页,令我比较出乎意料的是,facebook的首页的头部引入了大量的脚本(
![](https://dreamapple.me/2017/04/15/%E6%8A%8AJavaScript%E6%96%87%E4%BB%B6%E6%94%BE%E5%9C%A8%E6%96%87%E6%A1%A3%E7%9A%84%E5%A4%B4%E9%83%A8%E8%BF%98%E6%98%AF%E5%B0%BE%E9%83%A8/facebook-home-1.png)
facebook首页在head中引入的JavaScript
![](https://dreamapple.me/2017/04/15/%E6%8A%8AJavaScript%E6%96%87%E4%BB%B6%E6%94%BE%E5%9C%A8%E6%96%87%E6%A1%A3%E7%9A%84%E5%A4%B4%E9%83%A8%E8%BF%98%E6%98%AF%E5%B0%BE%E9%83%A8/facebook-home-2.png)
facebook首页在head中引入的JavaScript
不过基本上facebook的
这个属性是HTML5给
我们可以看到,虽然这些网站大部分的
还有百度首页的
还有一些比如Google和Baidu他们搜索页面同步加载的那些JavaScrip文件一些是为了在页面渲染之前做一些全局的处理(比如Google)添加了全局变量
![](https://dreamapple.me/2017/04/15/%E6%8A%8AJavaScript%E6%96%87%E4%BB%B6%E6%94%BE%E5%9C%A8%E6%96%87%E6%A1%A3%E7%9A%84%E5%A4%B4%E9%83%A8%E8%BF%98%E6%98%AF%E5%B0%BE%E9%83%A8/global-setting.png)
google搜索页面同步加载的JavaScript
还有的就是单纯的满足自己业务上的一些需求了,比如百度同步加载的那个JavaScript文件:
![](https://dreamapple.me/2017/04/15/%E6%8A%8AJavaScript%E6%96%87%E4%BB%B6%E6%94%BE%E5%9C%A8%E6%96%87%E6%A1%A3%E7%9A%84%E5%A4%B4%E9%83%A8%E8%BF%98%E6%98%AF%E5%B0%BE%E9%83%A8/baidu-search-sync-script.png)
baidu搜索页面同步加载的JavaScript
所以说,除了上面这些情况外,其它的情况下我们的脚本资源都需要放在文档的底部;当然这里还有一些需要我们注意的问题,首先,脚本加载的顺序很重要,比如如果你的脚本需要使用
![](https://dreamapple.me/2017/04/15/%E6%8A%8AJavaScript%E6%96%87%E4%BB%B6%E6%94%BE%E5%9C%A8%E6%96%87%E6%A1%A3%E7%9A%84%E5%A4%B4%E9%83%A8%E8%BF%98%E6%98%AF%E5%B0%BE%E9%83%A8/weibo-create-dom.png)
weibo通过脚本动态创建的元素
如果使用过一些框架的脚手架你就会发现,这些框架打包后的那个
到现在为止,我们已经讨论了很多关于把JavaScript文件放在文档的头部还是尾部的原因,那么下面我们可以总结出一些加载JavaScript文件的最佳实践;
对于必须要在DOM加载之前运行的JavaScript脚本,我们需要把这些脚本放置在页面的
对于支持使用
到这里为止,整篇文章就算是结束了,如果你还想进一步的了解关于JavaScript文件加载的一些知识,可以看看这篇文章
参考的一些资料:
Remove Render-Blocking JavaScript
Put Scripts at the Bottom
Best Practice: Where to include your script tags
Script Element
execCommand
What is difference between using JavaScript in head and body?
Where To Include JavaScript Files In A Document
Should I always put my JavaScript file in the head tag of my HTML file so that the code is loaded at the start?
Why put JavaScript in head
Deep dive into the murky waters of script loading
Asynchronous and deferred JavaScript execution explained
本作品保留所有权利。未获得许可前,不允许他人复制、发行、展览和表演作品。不允许他人基于该作品创作演绎作品。
我们今天来聊一聊关于JavaScript文件的引入位置的问题;大家在平时的Web开发中有没有想过这样一个问题,那就是我应该在文档的头部(也就是
<head>标签内部里面)引入所需要的JavaScript文件还是应该在尾部(也就是
</body>之前)引入所需要的JavaScript文件呢?今天我们就来深入的探究一下这个问题。
首先我们需要了解的一点就是,在浏览器渲染页面之前,它需要通过解析
HTML标记然后构建
DOM树。在这个过程中,如果解析器遇到了一个脚本(
script),它就会停下来,并且执行这个脚本,然后才会继续解析
HTML。如果遇到了一个引用外部资源的脚本(
script),它就必须停下来等待这个脚本资源的下载,而这个行为会导致一个或者多个的网络往返,并且会延迟页面的首次渲染时间。
还有一点是需要我们注意的,那就是外部引入的脚本(
script)会阻塞浏览器的
并行下载,HTTP/1.1规范表明,浏览器在每个主机下并行下载的组件不超过两个(也就是说,浏览器一次只能够同时从同一个服务器加载两个脚本);如果你网站的图片是通过多个服务器提供的,那么按道理来说,你的网站可以一次并行下载多张图片。但是,当我们网站在加载脚本的时候;浏览器不会再启动任何其它的下载,即使这些组件来自不同的服务器。
看到这里,也许很多开发者都会想:既然把脚本(
script)资源放在
head里面是个不好的主意,并且可能会阻塞浏览器渲染页面;那我们是不是要把所有的
JavaScript文件都放置到文档的底部呢?这个当然也是太过极端了,因为还是有一些情况需要我们在头部引用脚本的;到底是哪些情况需要我们这么做呢,下面我们来看看一些大公司的做法:
![](https://dreamapple.me/2017/04/15/%E6%8A%8AJavaScript%E6%96%87%E4%BB%B6%E6%94%BE%E5%9C%A8%E6%96%87%E6%A1%A3%E7%9A%84%E5%A4%B4%E9%83%A8%E8%BF%98%E6%98%AF%E5%B0%BE%E9%83%A8/google.png)
我们可以看到,这个搜索页面在头部加载了5个JavaScript文件(箭头标注的地方),其中两个JavaScript文件是内联的(
inline),另外三个大家可以看到
script标签上都添加了
async属性,那这个属性是干嘛的呢?我们会在下面解释。
![](https://dreamapple.me/2017/04/15/%E6%8A%8AJavaScript%E6%96%87%E4%BB%B6%E6%94%BE%E5%9C%A8%E6%96%87%E6%A1%A3%E7%9A%84%E5%A4%B4%E9%83%A8%E8%BF%98%E6%98%AF%E5%B0%BE%E9%83%A8/baidu.png)
baidu搜索页在head中引入的JavaScript
我们可以看到,百度也在头部引入了一些JavaScript文件,这些文件引入的方式与Google的做法差不多,都在引入外部资源的
script标签上添加了
async属性,除了第一个JavaScript文件没有那样做。
![](https://dreamapple.me/2017/04/15/%E6%8A%8AJavaScript%E6%96%87%E4%BB%B6%E6%94%BE%E5%9C%A8%E6%96%87%E6%A1%A3%E7%9A%84%E5%A4%B4%E9%83%A8%E8%BF%98%E6%98%AF%E5%B0%BE%E9%83%A8/stackoverflow.png)
stackoverflow首页在head中引入的JavaScript
![](https://dreamapple.me/2017/04/15/%E6%8A%8AJavaScript%E6%96%87%E4%BB%B6%E6%94%BE%E5%9C%A8%E6%96%87%E6%A1%A3%E7%9A%84%E5%A4%B4%E9%83%A8%E8%BF%98%E6%98%AF%E5%B0%BE%E9%83%A8/weibo.png)
weibo首页在head中引入的JavaScript
最后一个是facebook的首页,令我比较出乎意料的是,facebook的首页的头部引入了大量的脚本(
script),大家可以看一下截图
![](https://dreamapple.me/2017/04/15/%E6%8A%8AJavaScript%E6%96%87%E4%BB%B6%E6%94%BE%E5%9C%A8%E6%96%87%E6%A1%A3%E7%9A%84%E5%A4%B4%E9%83%A8%E8%BF%98%E6%98%AF%E5%B0%BE%E9%83%A8/facebook-home-1.png)
facebook首页在head中引入的JavaScript
![](https://dreamapple.me/2017/04/15/%E6%8A%8AJavaScript%E6%96%87%E4%BB%B6%E6%94%BE%E5%9C%A8%E6%96%87%E6%A1%A3%E7%9A%84%E5%A4%B4%E9%83%A8%E8%BF%98%E6%98%AF%E5%B0%BE%E9%83%A8/facebook-home-2.png)
facebook首页在head中引入的JavaScript
不过基本上facebook的
script标签上面都添加了
async属性,下面我们先来来说一下
script标签上面这个
async属性的作用。
这个属性是HTML5给
script新添加的属性,而且只适用于外部的JavaScript文件,如果在
script标签上添加了这个属性,那么表明这个脚本资源就不再是同步加载的了,而是异步加载的,所以不会阻塞浏览器对页面的渲染。当然这个属性会存在一些兼容性问题,一些浏览器还未实现对这个属性的支持。
我们可以看到,虽然这些网站大部分的
script标签(针对引入的外部文件)都添加了
async属性,但是还是有一些
script标签没有添加
async属性,那就表示这些资源是同步加载执行的,在这里你可能会问,那这些资源为什么不使用异步加载呢?原因很大程度上是因为,这些脚本需要在浏览器渲染页面之前就执行的;比如Yahoo在Best Practices for Speeding Up Your Web Site中就指出,如果你的脚本中使用了
document.write在页面中插入内容的话,那就不能够将这条脚本放置到文档的底部了。类似的还有weibo,weibo的
head中也使用了一个要在页面渲染之前就执行的脚本,如下:
1234 | <script type="text/javascript"> try {document.execCommand("BackgroundImageCache", false, true); } catch (e) {}</script> |
head中也有两条需要在页面渲染之前就执行的JavaScript文件:
1234567 | <script data-compress="strip">function h(obj){ obj.style.behavior='url(#default#homepag 4000 e)'; var a = obj.setHomePage('//www.baidu.com/');}</script><script>window._ASYNC_START=new Date().getTime();</script> |
![](https://dreamapple.me/2017/04/15/%E6%8A%8AJavaScript%E6%96%87%E4%BB%B6%E6%94%BE%E5%9C%A8%E6%96%87%E6%A1%A3%E7%9A%84%E5%A4%B4%E9%83%A8%E8%BF%98%E6%98%AF%E5%B0%BE%E9%83%A8/global-setting.png)
google搜索页面同步加载的JavaScript
还有的就是单纯的满足自己业务上的一些需求了,比如百度同步加载的那个JavaScript文件:
![](https://dreamapple.me/2017/04/15/%E6%8A%8AJavaScript%E6%96%87%E4%BB%B6%E6%94%BE%E5%9C%A8%E6%96%87%E6%A1%A3%E7%9A%84%E5%A4%B4%E9%83%A8%E8%BF%98%E6%98%AF%E5%B0%BE%E9%83%A8/baidu-search-sync-script.png)
baidu搜索页面同步加载的JavaScript
所以说,除了上面这些情况外,其它的情况下我们的脚本资源都需要放在文档的底部;当然这里还有一些需要我们注意的问题,首先,脚本加载的顺序很重要,比如如果你的脚本需要使用
jQuery库,那么你就应该在加载你的脚本之前先加载
jQuery库。其次,有些脚本是需要等到某些元素加载完成之后才可以执行的,那么你可以将你的脚本紧挨在那个元素的后面;还有一些元素是通过脚本动态创建的,所以它们也需要放在合适的位置。比如微博的:
![](https://dreamapple.me/2017/04/15/%E6%8A%8AJavaScript%E6%96%87%E4%BB%B6%E6%94%BE%E5%9C%A8%E6%96%87%E6%A1%A3%E7%9A%84%E5%A4%B4%E9%83%A8%E8%BF%98%E6%98%AF%E5%B0%BE%E9%83%A8/weibo-create-dom.png)
weibo通过脚本动态创建的元素
如果使用过一些框架的脚手架你就会发现,这些框架打包后的那个
index.html里面引入的外部JavaScript资源都是放在文档的底部的,并且它们也是按照顺序来的,
vendor.js文件(项目使用的框架,库打包形成的文件)先引入,然后才是
app.js文件(我们写的代码文件打包形成的),这就说明了引入脚本文件的顺序也是很重要的。
到现在为止,我们已经讨论了很多关于把JavaScript文件放在文档的头部还是尾部的原因,那么下面我们可以总结出一些加载JavaScript文件的最佳实践;
对于必须要在DOM加载之前运行的JavaScript脚本,我们需要把这些脚本放置在页面的
head中,而不是通过外部引用的方式,因为外部的引用增加了网络的请求次数;并且我们要确保内敛的这些
JavaScript脚本是很小的,最好是压缩过的,并且执行的速度很快,不会造成浏览器渲染的阻塞。
对于支持使用
script标签的
async和
defer属性的浏览器,我们可以使用这两个属性;其中需要注意的点就是,
async表示的意思是异步加载JavaScript文件,它的下载过程可以在HTML的解析过程中进行,加载完成之后立即执行这个文件的代码,执行文件代码的过程中会阻塞HTML的解析,它不保证文件加载的顺序。
defer表示的意思是在HTML文档解析之后在执行加载完成的JavaScript文件,JavaScript文件的下载过程可以在HTML的解析过程中进行,它是按照
script标签的先后顺序来加载文件的。更多详细的解释可以参考async vs defer attributes
到这里为止,整篇文章就算是结束了,如果你还想进一步的了解关于JavaScript文件加载的一些知识,可以看看这篇文章
参考的一些资料:
Remove Render-Blocking JavaScript
Put Scripts at the Bottom
Best Practice: Where to include your script tags
Script Element
execCommand
What is difference between using JavaScript in head and body?
Where To Include JavaScript Files In A Document
Should I always put my JavaScript file in the head tag of my HTML file so that the code is loaded at the start?
Why put JavaScript in head
Deep dive into the murky waters of script loading
Asynchronous and deferred JavaScript execution explained
本作品保留所有权利。未获得许可前,不允许他人复制、发行、展览和表演作品。不允许他人基于该作品创作演绎作品。
相关文章推荐
- js文件应该放在头部还是尾部?
- 到底JS文件的引入放置在头部好还是尾部好?
- [bat]批量替换文件头部和尾部
- 把外部JavaScript文件放在HTML底部
- JS文件放在头还是尾
- vim跳转文件头部和尾部
- vue引用公用的头部和尾部文件。
- JavaScript文件应该放在网页的什么位置
- dedecms 插件plus文件调用头部尾部的方法
- css文件放在头部的原因
- 声明和定义应该放在源文件还是头文件
- img的src更改失败原因:JS文件放在了头部引入
- 该把JS文件放在HTML文档的那个位置
- Zend Framework2-视图助手-在视图文件或控制器中追加脚本文件或脚本内容到头部或尾部
- #import 的位置究竟改放在h文件还是m文件中
- jsp文件放在WebRoot下还是WebInfo下
- 页面公共头部尾部文件的引用
- 将css放在头部,js放在尾部可以优化页面???
- HTML文档中头部文件介绍
- Yii模板头部引入css,尾部引入js文件