内联JavaScript应该放在HTML的哪个位置

简介: 内联JavaScript应该放在HTML的哪个位置

写在前面


内联JavaScript在现在的前端项目中是比较常见的,比如一些全局函数,全局统计逻辑等,我们可能会以内联JavaScript的方式写在HTML里。那么,内联JavaScript最好应该放在哪里呢?


页面渲染流程


首先来看看这个问题:页面是怎么渲染的?大致流程如下:

640.jpg

640.jpg

页面的渲染是一个复杂的过程,这里就不再详细说了。简单总结一下,就是使用HTML构建DOM树,CSS构建CSSOM,两者结合生成Render Tree,然后再进行渲染。


推荐几篇值得收藏,反复阅读的文章:



内联JS的位置


本文仅仅讨论在一般的情况下,内联JS应该放在哪个位置。首先,下面两点可以算是【共识】:


  1. JS尽量放在HTML底部。
  2. CSS尽量放在HTML头部。

JS放在底部是为了防止阻塞DOM的解析,CSS放在头部是为了尽早完成CSSOM的构建,从而尽早paint页面。下面是一个常见的页面的HTML代码:

<html>    <head>        <link href="xxx.css" rel="stylesheet">    </head>    <body>        <main>....</main>        <script src="xxx.js"></script>    </body></html>


假如我们有一段内联的、需要提前加载的、JS统计逻辑代码,很自然的,会把内联JS放在head里。那么是放在css前面,还是后面呢?这是本文将要阐述的问题。我做了两个实验来看看两个位置下的页面渲染流程。为了突出实验效果,我模拟的是3g下的网速。

内联JS在CSS之前


代码:


<html>    <head>        <script type="text/javascript">            for (var i = 0; i < 100000000; i++) {}</script>        <link href="https://cdn.bootcss.com/twitter-bootstrap/4.3.1/css/bootstrap-grid.css" rel="stylesheet">    </head>    <body>        <p>hello word_1</p>        <p>hello word_2</p>        <p>hello word_3</p>        <p>hello word_4</p>        <p>hello word_5</p>        <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>    </body></html>


timeline如下:

640.jpg

eventlog如下:

640.jpg

从上面两个图可以看到,开始解析HTML后,会开始执行内联JS,并且发起网络请求下载CSS和JS文件,当CSS下载完成后,便开始进入渲染。


内联JS在CSS后


代码:


<html>    <head>        <link href="https://cdn.bootcss.com/twitter-bootstrap/4.3.1/css/bootstrap-grid.css" rel="stylesheet">        <script type="text/javascript">            console.log(document.getElementById, window);            for (var i = 0; i < 100000000; i++) {}</script>    </head>    <body>        <p>hello word_1</p>        <p>hello word_2</p>        <p>hello word_3</p>        <p>hello word_4</p>        <p>hello word_5</p>        <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>    </body></html>


timeline如下:

640.jpg

eventlog如下:

640.jpg

从上面两个图可以看到,浏览器开始解析HTML后,会发起网络请求下载JS和CSS,当CSS下载完成后,才会继续执行内联JS,页面的渲染被推迟了,推迟的时间就是内联JS的执行时间。


实验小结


  1. 浏览器解析HTML的时候,会对整个HTML进行『preload scanner』,提前发起网络请求,下载外链资源,并不是解析到对应标签才会进行下载。而外链下载这个过程是由浏览器进程的网络线程完成的,不会阻塞当前渲染器进程的主线程逻辑。
  2. JS会阻塞HTML的解析。内联JS在CSS前面的时候,执行内联JS可以和网络请求并行执行,执行完内联JS后会继续解析HTML,并且在CSS文件下载完成后,选择合适的时机进行渲染。而内联JS在CSS后面的时候,由于考虑到内联JS可能会修改CSSOM,所以主线程会暂停,直到CSS下载完成,生成CSSOM后,才会继续执行内联JS、解析HTML。


结论


对于一些全局函数,全局统计逻辑等,我们往往会以内联JS的形式放在HTML内的head里。此时,最好把内联JS放在外链CSS之前,以提高首屏速度,至少不会拖慢首屏速度。


写在后面


本文聚焦探索了内联JS在HTML内的最佳位置。网上关于页面渲染流程的文章很多,而自己去亲自实践后,才能更好的理解整个渲染流程。符合预期。

推荐阅读


客户端内H5页面的首屏性能优化


使用service worker做缓存来加快首屏速度,可行么?


当考虑网页首屏时长优化的时候,我们在考虑什么?

相关文章
|
5月前
|
移动开发 前端开发 JavaScript
征信报告修改器,征信报告生成器,制作软件无痕修改软件【js+html+css】
本项目为信用评分模拟器教学工具,采用HTML5实现,仅供学习参考。核心功能通过JavaScript构建,包含虚拟数据生成、权重分配及信用因素分析(如还款记录、信用使用率等)。
|
5月前
|
存储 自然语言处理 前端开发
抖音快手小红书虚拟评论截图生成器,模拟对话制作工具,html+js+css
这是一款纯前端实现的多平台虚拟评论生成器,支持抖音、快手、小红书风格,适用于产品演示与UI设计。采用Vanilla JS与Flexbox布局,利用IndexedDB存储数据,CSS Variables切换主题。
|
5月前
|
前端开发 JavaScript
个人征信电子版无痕修改, 个人信用报告pdf修改,js+html+css即可实现【仅供学习用途】
本代码展示了一个信用知识学习系统的前端实现,包含评分计算、因素分析和建议生成功能。所有数据均为模拟生成
|
4月前
|
开发框架 JavaScript 前端开发
精选HTML、JavaScript、ASP代码片段集锦
这些代码片段代表了HTML, JavaScript和ASP的基本应用,可被集成到更复杂的项目中。它们注重实用性,并且易于理解,旨在帮助开发者快速开始项目构建或进行学习。尽管ASP不如其他服务器端技术(如Node.js, PHP, Ruby等)现代,但它在遗留系统中仍非常普遍,了解基础仍具有价值。
162 14
|
5月前
|
存储 前端开发 安全
病历单生成器在线制作,病历单生成器app,HTML+CSS+JS恶搞工具
本项目为医疗病历模拟生成器,旨在为医学教学和软件开发测试提供数据支持,严格遵守《医疗机构病历管理规定》。
|
5月前
|
前端开发 容器
处方单图片生成器, 处方单在线制作免费,js+css+html恶搞神器
这是一个电子处方模拟生成系统,使用html2canvas库实现图片导出功能。系统生成的处方单包含多重防伪标识,并明确标注为模拟数据,仅供学习
|
5月前
|
前端开发
个人征信PDF无痕修改软件,个人征信模板可编辑,个人征信报告p图神器【js+html+css仅供学习用途】
这是一款信用知识学习系统,旨在帮助用户了解征信基本概念、信用评分计算原理及信用行为影响。系统通过模拟数据生成信用报告,涵盖还款记录
|
5月前
|
前端开发 JavaScript 容器
制作b超单生成器, 假怀孕b超单图片制作, p图医院证明【css+html+js装逼恶搞神器】
本资源提供一个适合用于熟人之间恶搞的工具,效果逼真,仅供学习参考与娱乐。包含前端技术学习要点:语义化布局、响应式设计、Flexbox、图片自适应
|
5月前
|
前端开发
医院检查单子p图软件,在线制作仿真病历,js+css+html装逼神器
本示例展示如何用HTML/CSS创建医疗信息页面,内容仅供学习参考。页面模拟“阳光医院体检中心”场景,提供预约功能验证(如姓名、手机号、日期)。所有数据仅用于演示