Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[html] 第22天 js放在html的<body>和<head>有什么区别? #74

Open
haizhilin2013 opened this issue May 7, 2019 · 14 comments
Open
Labels
html html

Comments

@haizhilin2013
Copy link
Collaborator

js放在html的<body><head>有什么区别?

@haizhilin2013 haizhilin2013 added the html html label May 7, 2019
@haizhilin2013 haizhilin2013 changed the title [html] 第22天 js放在html的<body><head>有什么区别? [html] 第22天 js放在html的<body>和<head>有什么区别? May 7, 2019
@Rong-CC
Copy link

Rong-CC commented May 8, 2019

浏览器解析html从上往下执行,放在head先执行js了,会造成dom树还没有生成就执行js。

@onloner2012
Copy link

head标签准确来说,是对html文档的一种配置

@yxkhaha
Copy link

yxkhaha commented May 8, 2019

  • 放在head 比放在body先解析,放在head里在被调用时才执行,body里加载的时候执行

@Konata9
Copy link

Konata9 commented Aug 6, 2019

js 放在 <head> 中,如果不添加 async 或者 defer 时,当浏览器遇到 script 时,会阻塞 DOM 树的构建,进而影响页面的加载。当 js 文件较多时,页面白屏的时间也会变长。

在这个过程中,如果解析器遇到了一个脚本(script),它就会停下来,并且执行这个脚本,然后才会继续解析 HTML。如果遇到了一个引用外部资源的脚本(script),它就必须停下来等待这个脚本资源的下载,而这个行为会导致一个或者多个的网络往返,并且会延迟页面的首次渲染时间。

把 js 放到 <body> 里(一般在 </body> 的上面)时,由于 DOM 时顺序解析的,因此 js 不会阻塞 DOM 的解析。对于必须要在 DOM 解析前就要加载的 js,我们需要放在 <head> 中。

参考文章:
该把 JS 文件放在 HTML 文档的那个位置

@seho-dev
Copy link

seho-dev commented Aug 8, 2019

在浏览器解析HTML中的时候,如果在head标签中遇到了script标签并且是同步执行的,那么就会影响文档的加载,如果引入的过多的同步脚本文件
那么加载会变得非常怪异且卡顿;但是放在body中,根据script标签,从上到下的解析顺序,它不会对html进行阻塞;

那么在一般业务中我们如何做呢?一般情况下是在网站中,同步在head加载的脚本通常是业务必须的,比如说我要注册一个window对象,或者用document.write写入一些内容,或者是业务需求,我们可以用head来做加载,
就是意味着没有这个脚本,下面的文档走不下去;
那么我们也可以在头部给script标签加入async的属性,表示它是异步加载的脚本,不会对html进行阻塞,这也是大部分网站的做法;
除了上面的情况我们都需要把js引入到底部或者body中合适的位置,比如说我的jq从那个html代码进行了使用,那么就在它之前均可;

@wython
Copy link

wython commented Dec 10, 2019

js 放在 <head> 中,如果不添加 async 或者 defer 时,当浏览器遇到 script 时,会阻塞 DOM 树的构建,进而影响页面的加载。当 js 文件较多时,页面白屏的时间也会变长。

在这个过程中,如果解析器遇到了一个脚本(script),它就会停下来,并且执行这个脚本,然后才会继续解析 HTML。如果遇到了一个引用外部资源的脚本(script),它就必须停下来等待这个脚本资源的下载,而这个行为会导致一个或者多个的网络往返,并且会延迟页面的首次渲染时间。

把 js 放到 <body> 里(一般在 </body> 的上面)时,由于 DOM 时顺序解析的,因此 js 不会阻塞 DOM 的解析。对于必须要在 DOM 解析前就要加载的 js,我们需要放在 <head> 中。

参考文章:
该把 JS 文件放在 HTML 文档的那个位置

上面很多都是纸上谈兵,这个回答相对靠谱。我做一些补充。

关于这个问题,我自己写个后端延迟脚本试验过。讲清楚区别,首先要了解浏览器渲染大过程。我们老生常谈,一般浏览器渲染过程分为,html解析-->dom树构建-->渲染树构建-->渲染树布局-->渲染树呈现 这样一个过程。

在以上过程中,需要了解的是,渲染树构建和dom树构建的区别,渲染树实际上是css展示样式和dom树结合创建过程,此过程依赖css的样式。而渲染树布局依赖css的布局样式。

基于上面的论点,也就是说,页面需要展示内容的过程是依赖css,而普通js脚本的加载又是依赖css正在加载的脚本的。

接下来回到上面的问题,js放在head和放在body的区别首先要搞清楚是有没css影响,有css影响时候是在css前还是css后面。

  1. 没有css的情况下。
    那么浏览器到渲染到script脚本时候需要等待script脚本的载入和运行。这是两个过程,两个过程都是阻塞的。
    这也就导致,如果在head中放了script标签,因为html解释过程是边解析边输出(dom),此是在等待js完成后,由于上面的dom树构建部分还未完成,如果js有使用到dom的脚本,那么会报错。如果只是单纯的console.log其实是没有问题的。

放在body后,html解析到这里的时候dom树基本构建完成。js脚本加载和执行都不会有任何影响。而且这两种都页面解析是停止的。需要讨论异步情况,要关注defer和async两个属性。这里不做深究。

  1. 在有css情况下
    浏览器的渲染中,dom树是会继续构建,但是js在css后面的时候,需要等待真正加载css完成才会执行。css过程不会阻塞页面dom树的构建,但是会阻塞渲染树的构建。此时反正body后会受延迟css的影响,不延迟不影响。defer和async默认会认为与css不相关,不受css影响。反正css前和1讨论没区别。

@blueRoach
Copy link

blueRoach commented Jun 11, 2020

  • html渲染是从上至下,依次构建DOM树=>渲染树,如果遇到CSS会阻止渲染树的构建,如果遇到脚本(JS)则DOM树和渲染树都会停止构建。
  • 由于JS文件一般要请求接口、文件和做复杂的处理,放在body的后面可以先让HTML和CSS先渲染出来,展示界面。不至于傻傻等JS执行完,去展示一段时间的空白。
  • 所以我们要把JS放到前面或者添加 async 或者 defer属性,这样不管JS如何都不会影响界面样式和结构的展示速度

@qiqingfu
Copy link

qiqingfu commented Jun 15, 2020

浏览器解析 html 文件是从上至下的,暂且不谈论 css 文件的引入,只谈 js 文件和 html dom 标签。

说到 <script> 标签,那么它是具有两个属性的。async 异步加载 和 defer 延迟加载。

<script>

script 标签 放在 head 中,并且这个 script 标签只有 src 属性引入外部 js 文件的情况下,html 文件开始渲染,直到命中 script 标签,此时解析将停止,并发出一个请求获取该文件并执行。执行结束之后继续渲染 html 标签。

<script async>

使用 async 会在 html 解析期间下载文件,并在下载完成后暂停 html 的解析,执行下载的外部 js 文件。直接后继续解析 html

<script defer>

它和 async 的区别是,同样在 html 解析期间下载外部的 js 文件,但是下载完成后不会立即执行 js 脚本文件,而是等到 html 解析完成后才执行它。 即在 DOMContentLoaded 之间执行已下载的 外部 js 文件。

什么场景下使用 asyncdefer 呢?

  1. 如果 script 是模块化,并且不依赖于任何脚本,那么使用 async
  2. 如果脚本依赖于或者被另一个脚本依赖,那么使用defe

当把 script 脚本放在 body 标签内就不用解释了吧。和 <script defer> 很像不是么?

@MrZ2019
Copy link

MrZ2019 commented Sep 22, 2020

html渲染是从上至下,依次构建DOM树=>渲染树,如果遇到CSS会阻止渲染树的构建,如果遇到脚本(JS)则DOM树和渲染树都会停止构建。
由于JS文件一般要请求接口、文件和做复杂的处理,放在body的后面可以先让HTML和CSS先渲染出来,展示界面。不至于傻傻等JS执行完,去展示一段时间的空白。
所以我们要把JS放到前面或者添加 async 或者 defer属性,这样不管JS如何都不会影响界面样式和结构的展示速度

@songlovena
Copy link

get ()

@xiezhenghua123
Copy link

js放在head里面会阻塞dom树的加载
放在body里面不会

@zxcdsaqwe123
Copy link

放在中,则无法直接获取网页中的元素,获取元素的代码需要放在window.onload中

@amikly
Copy link

amikly commented Nov 9, 2021

  • 在HTML body部分中的js会在页面加载的时候被执行。
  • 在HTML head部分中的js会在被调用的时候才执行,但是在主页和其余部分代码之前预先装载
    从JavaScript对页面下载性能方向考虑:由于脚本会阻塞其他资源的下载(如图片等)和页面渲染,直到脚本全部下载并执行完成后,页面的渲染才会继续,因此推荐将所有的<script>标签尽可能放到<body>标签的底部,以尽量减少对整个页面下载的影响

@Iambecauseyouare
Copy link

放在body中,会在页面加载的时候执行
放在head中,被调用的时候才执行

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
html html
Projects
None yet
Development

No branches or pull requests