(题图:梵高-向日葵)


我们最开始学前端的时候都会看到教程在处理外部css,js的时候会将css放在header中,js放在body的最后。为什么要这样子处理,今天参考一些资料好好分析下。

为什么外链css为什么要放头部?#

首先整个页面展示给用户会经过html 的解析与渲染过程。

外链css无论放在html的任何位置都不影响html的解析,但是影响html的渲染。

如果将css放在尾部,html的内容可以第一时间显示出来,但是会阻塞html行内css的渲染。

浏览器的这个策略其实很明智的,想象一下,如果没有这个策略,页面首先会呈现出一个行内css样式,待CSS下载完之后又突然变了一个模样。用户体验可谓极差,而且渲染是有成本的。

如果将css放在头部,css的下载解析是可以和html的解析同步进行的,放到尾部,要花费额外时间来解析CSS,并且浏览器会先渲染出一个没有样式的页面,等CSS加载完后会再渲染成一个有样式的页面,页面会出现明显的闪动的现象。

为什么script要放在尾部?#

因为当浏览器解析到script的时候,就会立即下载执行,中断html的解析过程,如果外部脚本加载时间很长(比如一直无法完成下载),就会造成网页长时间失去响应,浏览器就会呈现“假死”状态,这被称为“阻塞效应”。

具体的流程是这样的:

  1. 浏览器一边下载HTML网页,一边开始解析。
  2. 解析过程中,发现script标签
  3. 暂停解析,网页渲染的控制权转交给JavaScript引擎
  4. 如果script标签引用了外部脚本,就下载该脚本,否则就直接执行
  5. 执行完毕,控制权交还渲染引擎,恢复往下解析HTML网页

外链的script包含async或者defer如何处理?#

这两个属性只是script标签在header标签中使用的,如果你把它放在body后面是无效的。

script 的这两个属性主要用于其js文件没有操作DOM的情况,这时候就可以将该js脚本设置为异步加载,通过async或defer来标记代码。

async和defer的区别:

0、async和defer都仅对外部脚本有效,对于内置而不是连接外部脚本的script标签,以及动态生成的script标签不起作用。

1、async和defer虽然都是异步的,不过使用async标志的脚本文件一旦加载完成就会立即执行;而使用defer标记的脚本文件,会在 DOMContentLoaded 事件之前(也就是页面DOM加载完成时)执行。

2、如果有多个js脚本文件,async标记不保证按照书写的顺序执行,哪个脚本先下载结束,就先执行那个脚本。而defer标记则会按照js脚本书写顺序执行。

3、一般来说,如果脚本之间没有依赖关系,就使用async属性,如果脚本之间有依赖关系,就使用defer属性。如果同时使用async和defer属性,后者不起作用,浏览器行为由async属性决定。

对于async标记,浏览器的解析过程是这样的:

  • 浏览器开始解析HTML网页

  • 解析过程中,发现带有async属性的script标签

  • 浏览器继续往下解析HTML网页,同时并行下载script标签中的外部脚本

  • 脚本下载完成,浏览器暂停解析HTML网页,开始执行下载的脚本

  • 脚本执行完毕,浏览器恢复解析HTML网页

对于defer标记,浏览器的解析过程是这样的:

  • 浏览器开始解析HTML网页

  • 解析过程中,发现带有defer属性的script标签

  • 浏览器继续往下解析HTML网页,同时并行下载script标签中的外部脚本

  • 浏览器完成解析HTML网页,此时再执行下载的脚本

  

由于使用了async或defer的script会放在header中,而header又会存在外链css,那么二者有顺序要求吗?

header中script和外链css的位置顺序#

先说结论:

如果在html的header中同时有js脚本和外链css,js脚本最好放外链css前面。

其实js的执行是依赖css样式的。即只有css样式全部下载完成后才会执行js。

因为如果脚本的内容是获取元素的样式,宽高等CSS控制的属性,浏览器是需要计算的,也就是依赖于CSS。浏览器无法感知脚本内容到底是什么,为避免样式获取错误,因而只好等前面所有的样式下载完后,再执行JS。
也就是说,如果有外链css,那么js的执行时需要等待外链css下载完


(added in 20191204)

根据一些网友的评论与反馈,然后查了一些资料,暂时得出的结论如下:

由于现代浏览器很聪明会进行 prefetch 优化,就如 Chrome 浏览器,它会在解析 HTML 时收集外链,并在后台并行下载,由于会并行下载,那么head中外链js和css的位置其实就没有什么很大影响了。

参考链接:

  • JS 和 CSS 的位置对其他资源加载顺序的影响
  • 使用 Proload/Prefetch 优化你的应用

(啾咪 ^.<)

为什么css放头部、js放尾部相关推荐

  1. php 鼠标小手,CSS如何让鼠标放上时的小手样式

    CSS实现让鼠标放上时出现小手样式的方法:首先创建一个HTML示例文件:然后在body中添加一个span标签:接着给该标签添加"cursor:pointer;"样式来实现让鼠标放上 ...

  2. css中一行内容放不下,需要用省略号来代替

    记录一下第一次写文章,有不对的地方请多指教 css中一行内容放不下,需要用省略号来代替 .title{ white-space: nowrap;overflow: hidden;text-overfl ...

  3. CSS中调用JS函数和变量

    在CSS来调用JS程序. 这个技术是网络安全里的,叫做CSS跨站. 我们知道CSS里是可以控制某些HTML元素的属性的,譬如background-image等等,而在URL里添加Javascript: ...

  4. css动画和js动画_CSS与JS动画:哪个更快?

    css动画和js动画 How is it possible that JavaScript-based animation has secretly always been as fast - or ...

  5. 【译】CSS动画 vs JS动画

    原文地址 目前有两个主流的方法在web上创建动画:使用CSS或JS.到底选择哪种方法来实现动画,完全取决于你的项目以及你想要达到的效果. tips: 对于简单的只出现一次的过渡效果,可以采用CSS动画 ...

  6. node中怎样将css导入到html,CSS无法使用Node.js加载到我的HTML代码中

    我想通过Node.js使用express()函数在localhost:3000中将CSS添加到我的HTML中. 不幸的是,有些奇怪.我一步一步按照教程中的步骤,但仍然无法加载我的CSS.我的style ...

  7. html js不触发_图文详解鼠标事件CSS:hover和JS:mouseover的区别

    在工作中为了使页面更具有吸引力,前端开发人员经常会在页面中加上鼠标移入和移出的效果.鼠标移入移出的设置,一般有两种方法,一种是单纯用CSS中的hover伪类,另一种可以用JS 中的DOM事件,即onm ...

  8. 客户端页面不更新CSS样式或JS脚本的方法 (2018-08-17 17:33)

    js或css后加?v= 版本号的用法 <span style="font-size:14px;">css和js带参数(形如.css?v=与.js?v= 或 .css?v ...

  9. [JavaWeb-Bootstrap]CSS样式和JS插件

    CSS样式和JS插件 1. 全局CSS样式:* 按钮:class="btn btn-default"* 图片:* class="img-responsive": ...

最新文章

  1. androidsettitle方法_Android使用setCustomTitle()方法自定义对话框标题
  2. Android存储系统之架构篇
  3. ar ebs 销售订单关闭_有关销售订单的工作流(workflow)定义和处理方式
  4. term和match查询总结(中文检索)
  5. rest framework 节流
  6. Eclipse 基于接口编程的时候,快速跳转到实现类的方法(图文)
  7. c语言鼠标游戏,c语言写的鼠标操作的五子棋游戏,欢迎观赏!
  8. 你的主机中的软件中止了一个已建立的连接
  9. 视频监控系统的软件设计开发方案
  10. 22 个最常用的Python包
  11. win7下使用变色龙引导linux
  12. 上位机和FPGA开发板--串口通信实验
  13. 2023年春招热门笔试算法题(C++)
  14. AS百度地图定位APP
  15. English 900
  16. Java绘画板源码_Java 绘图板 示例源码下载(画板)
  17. 计算机毕业设计之Android的游戏账号交易平台APP(源码+系统+mysql数据库+Lw文档)
  18. 企业微信代运营方案怎么做 微信代运营网站有哪些
  19. ssm校园失物招领系统毕业设计源码080008
  20. 计算机网络——各种时延的计算

热门文章

  1. 【外文翻译】外国友人写得很不错的Java Lambda表达式入门教程,我终于翻译好给大家啦!!!...
  2. 大数据信息资料采集:刘润公众号历史商业评论文章采集评论搜集
  3. 浅析即时通讯开发P2P技术如何降低实时视频直播带宽
  4. Scala 可变集合体系、不可变集合体系 详解
  5. 昨天同事lastday,把前端测试包扔线上去了
  6. 左右两侧浮动广告代码
  7. 在一个批处理系统中有两个作业进程,一个作业序列其到达时间及估计运行时间如下表作业 到达时间
  8. C语言用双曲线函数拟合曲线,c语言绘制函数曲线
  9. » 用HSCALE实现MySQL的数据分布式存储 江边潮未尽,枫红一季秋 -- NinGoo's blog
  10. 【基础知识】BSS段,数据段,代码段,堆栈段