youking-lib / fumble Goto Github PK
View Code? Open in Web Editor NEWTry to understand...
Try to understand...
以前我们谈性能优化,关键指标是页面 PLC(加载时间)
,简单的定义就是:浏览器中的加载旋转图标停止时间。
而当前,我们构建的不再是一个网页而是一个动态、交互的应用。现在我们来看看网络性能在其优化历程中是如何一步步的提高的。
为什么 "样式在上,脚本在下" 是最佳实践?
要回答这个问题,我们得首先回顾一下浏览器的架构,了解解析、布局和脚本之间如何相互配合在屏幕上绘制出像素来。
浏览器在解析 HTML
文档的基础上构建 DOM
,同时也会 CSS 对象模型,这两个模型共同创建了 渲染树
,之后浏览器就会在屏幕上绘制图形。
优化运行时的渲染和脚本执行固然至关重要,但对于运行在浏览器中的应用来说,迅速而有效的获取网络资源才是第一要义
那么 HTTP 如何有效的获取网络资源?
在 HTTP1.0 中,每个 TCP 链接开始都有三次握手,要经历一次客户端与服务器间的完整往返。
而在支持持久连接的情况下,就可以避免第二次 TCP 连接时的三次握手、消除另一次 TCP 满启动的往返,节约网络请求。
HTTP1.1 默认启用持久连接,可以在 HTTP 首部添加:
Connection: Keep-Alive
字段来明确要求服务器使用持久连接。
持久连接对连接的性能提升巨大,但浏览器在一次请求发起后呆呆的等待服务器的相应却也不是办法。
然后大多数现代浏览器支持了主机打开6个连接,这意味着:
这样感觉浏览器可以欢快的加载网络资源了。但是这样的代价、成本却提高了,CPU 占用率提高了,浏览器的开发成本也提高了。
总体来说,这还是没有从根本上解决 HTTP 的限制,是客户端对于web性能提升的一个权宜之计。
为什么限制每个主机最多6个连接,如果客户端超过了最大的连接数,那么后来的所有的客户端请求都会被阻塞。比如,在一个主机上同时打开6个并行下载,再打开第七个请求时,这个请求会挂起,直到前面的请求完成才会执行。这样的情况并不是罕见,比如在应用中,
websocket
、Server sent event
和挂起xhr
,都会占用一个 TCP 连接。
HTTP2.0 中新的二进制分帧层将 HTTP 消息分解为互不依赖的帧,然后乱序发送,最后在另一端重新组合起来。
有点懵,通过一幅图来了解原理:
HTTP2.0 把消息分解为独立帧,交错发送,然后在另一端按照每个包重新组装(有木有像坐地铁的感觉),就实现了一个连接上有多个请求和响应,从而带来了巨大的性能提升:
并行交错的发送请求、发送响应,请求之间、响应之间户不影响
一个连接可以并行发起多个请求和响应
消除不必要的延迟,从而减少页面加载时间
等等...
参考
Web 性能权威指南
HTTP/2 for a Faster Web
首先我们搭建一个简单的web服务
const express = require('express')
const path = require('path')
const app = express()
app.set('views', path.join(__dirname, 'view'))
app.set('view engine', 'ejs')
app.use('/public', express.static(path.join(__dirname, 'static')));
app.get('/', (req, res) => {
res.render('index')
})
app.listen(8096, () => {
console.log('Server running at port: 8096')
})
本地网速可能过快,建议用 chrome 模拟3g网速
浏览器请求中,我们先看看返回资源的时间轴:
很明显的看出先加载 HTML 文件,然后开启三个 TCP 连接并发请求 main.css
、jquery_1.js
、main.js
三个文件。
还记得我们的 TCP 的最大连接数是六个吗?如果我们同时请求六个以上的文件会发生什么?
由上图我们可以看出,在解析完 HTML 之后,并发发起了 main.css
、jquery_1.js ~ jquery_5.js
六个请求,而当 main.css
文件加载完,不在占用一个 TCP 连接,那么浏览器立即去请求了 jquery_6
,以此类推。
有个细节我们需要注意一下:
当在地址栏输入URL后,DNS寻址开始到三次握手的时间可以计入上图的 DNS Lookup
、Initial connection
中,当持久连接开启时,这个 TCP 已经寻址和握手,在以后的重用中,都不会再 DNS 寻址和三次握手。
而当我们再打开一个 TCP 连接时,即新建的这个 TCP 连接还是会进行 DNS 寻址和三次握手。
以上两次都是浏览器在请求头中默认 connection: keep-alive
,服务器返回:
// 待补充
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.