浏览器什么时候会发起网络请求,去加载一张图片?

简介: 浏览器什么时候会发起网络请求,去加载一张图片?

写在前面


浏览器在什么时候会去加载一张图片呢?当然是我们网页中有图片的时候。在平时的项目开发中,我们还常常会用图片进行日志上报,大概像下面这样:


var img = new Image();img.src = 'http://上报地址?a=1'


新建一个Image,将其src赋值,浏览器便会发出一个网络请求。

再来考虑一下下面的代码:


var scriptEl = document.createElement('script');scriptEl.src = 'http://xxxx.js';


上面的代码会发起网络请求么?

答案是:不会。只需要增加一行代码,将script插入到DOM树中,便会触发网络请求。


var scriptEl = document.createElement('script');scriptEl.src = 'http://xxxx.js';document.body.appendChild(scriptEl); // 这行代码会触发请求


什么时候会触发一次图片请求?

再来看下面的代码:


var imgStr = '<img src="xxx.png">';var divEl = document.createElement('div');divEl.innerHTML = imgStr;


上面的代码会触发网络请求么?答案是:会的。虽然divEl并没有被插入到DOM树中,但是网络请求依然会触发。这种表现一开始是让我有点意外的。于是乎,我开始了探索。

翻了一下html规范,发现了下面这段话:

640.jpg

地址:https://html.spec.whatwg.org/multipage/images.html#when-to-obtain-images


大概的意思就是:


如果浏览器禁用了js脚本,那么浏览器可以立即请求图片,也可以根据需要加载图片。如果浏览器没有禁用js脚本,当img元素被创建,或者经历一些变化(src被赋值等) 时,浏览器必须立即进入一个update the image data的流程。在update the image data这个流程中,如果图片元素还没有内容,并且图片元素的src已被赋值,浏览器会立即发起请求去请求图片。


这样,就可以解释上述的现象了:


Case 1


var img = new Image();img.src = 'http://上报地址?a=1'
// Object.prototype.toString.call(img) === "[object HTMLImageElement]"


使用Image构造函数时,生成了一个HTMLImageElement实例,也就是一个img元素,然后给这个img元素的src赋了值。很显然,我们使用了javascript。按照规范,浏览器必须立即发起网路请求,更新图片数据。


Case 2


var imgStr = '<img src="xxx.png">';var divEl = document.createElement('div');divEl.innerHTML = imgStr;
// Object.prototype.toString.call(divEl.firstChild) === "[object HTMLImageElement]"


在使用了innerHTML后,其实我们也是生成了一个HTMLImageElement实例。按照规范,浏览器也必须立即发起网络请求,更新图片数据。


总结一下:只要我们在代码中创建了一个img元素(HTMLImageElement实例),并且我们给这个img元素的src赋值了,那么浏览器就会发起网络请求,加载图片内容

什么时候触发一次script请求


我们再来规范里是怎么规定script标签的。


地址:https://html.spec.whatwg.org/multipage/scripting.html#prepare-a-script

640.jpg

在script标签的相关规范里,我没有找到明确的说明在什么情况下需要发起网络请求加载资源。另外,我看到了上面红框里的这段话。概括一下,就是:


浏览器可以在设置script元素的src时候,就发起网络请求加载资源。但是如果最后,这个script元素没有插入DOM的话,网络请求就完全被浪费了。


可以理解为:浏览器可以在设置script元素的时候,自行考虑是否需要立即发起网络请求加载资源。然后浏览器在实现的时候,为了节约资源,并没有立即发起请求,而是选择了在插入DOM树后,才发起请求。


(这里不是很确定,但是没有找到更进一步的说明)


跳出规范来思考


先不看规范,在平时的业务中,我们新建图片后,不管图片是否最终插入DOM树,都需要立即拿到图片的信息,比如canvas,比如通过图片的宽高进行页面排版等。因此,新建img元素后立即发起请求拿到图片数据,是合乎逻辑的

对于script元素来说,也不存在需要单独操作的场景,为了节省资源,script插入DOM树后再发起网络请求,也是合乎逻辑的。


写在后面


在业务开发中,某些代码看起来很理所当然,便没有多想。偶尔会遇到让人意外的表现,这个时候探索一下,加深一下理解,虽然有钻牛角尖的嫌疑,也算是符合预期吧。

相关文章
|
机器学习/深度学习 PyTorch 算法框架/工具
目标检测实战(一):CIFAR10结合神经网络加载、训练、测试完整步骤
这篇文章介绍了如何使用PyTorch框架,结合CIFAR-10数据集,通过定义神经网络、损失函数和优化器,进行模型的训练和测试。
531 2
目标检测实战(一):CIFAR10结合神经网络加载、训练、测试完整步骤
|
4月前
|
前端开发
WebView2 控件(基于 Microsoft Edge (Chromium) 的嵌入式浏览器控件),保存资源(图片、脚本、CSS)
WebView2 控件(基于 Microsoft Edge (Chromium) 的嵌入式浏览器控件),保存资源(图片、脚本、CSS)
261 37
|
移动开发 TensorFlow 算法框架/工具
只保存和加载网络权重
【8月更文挑战第21天】只保存和加载网络权重。
91 2
|
XML 缓存 JSON
为什么浏览器中有些图片、PDF等文件点击后有些是预览,有些是下载
为什么浏览器中有些图片、PDF等文件点击后有些是预览,有些是下载
605 0
|
8月前
|
数据采集 消息中间件 JavaScript
浏览器渲染揭秘:从加载到显示的全过程;浏览器工作原理与详细流程
了解浏览器工作原理与流程,能有效帮助前端开发与性能优化。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
12月前
|
缓存 监控 前端开发
在资源加载优化中,如何利用浏览器缓存提升性能?
通过以上这些方法,可以有效地利用浏览器缓存来提升资源加载的性能,减少网络请求次数,提高用户体验和应用的响应速度。同时,需要根据具体的应用场景和资源特点进行灵活调整和优化,以达到最佳的效果。此外,随着技术的不断发展和变化,还需要持续关注和学习新的缓存优化方法和策略。
342 53
|
10月前
|
Ubuntu Linux 开发者
Ubuntu20.04搭建嵌入式linux网络加载内核、设备树和根文件系统
使用上述U-Boot命令配置并启动嵌入式设备。如果配置正确,设备将通过TFTP加载内核和设备树,并通过NFS挂载根文件系统。
535 15
|
缓存 JavaScript
Vue加载网络组件(远程组件)
【10月更文挑战第23天】在 Vue 中实现加载网络组件(远程组件)可以通过多种方式来完成。
|
安全 Oracle Java
edge浏览器加载java插件
edge浏览器加载java插件
783 1
|
网络协议 前端开发 JavaScript
浏览器加载网页的幕后之旅:从URL到页面展示详解
【8月更文挑战第31天】当在浏览器地址栏输入URL并回车后,一系列复杂过程随即启动,包括DNS解析、TCP连接建立、HTTP请求发送、服务器请求处理及响应返回,最后是浏览器页面渲染。这一流程涉及网络通信、服务器处理和客户端渲染等多个环节。通过示例代码,本文详细解释了每个步骤,帮助读者深入理解Web应用程序的工作机制,从而在开发过程中作出更优决策。
329 5