Webkit系列:第二回(HTML解释器和DOM模型)
本文将尽可能的解释Webkit的HTML解释器流程及Dom模型相关的知识点在前文介绍从输入url到页面的最终呈现的过程,其中有一步:渲染器进程获取到资源后会将html资源给到html解释器,用来生成dom节点最终生成dom树形结构的对象。那么html解释器具体做了啥呢?
总体流程:字节流被解码成字符流,字符流通过词法分析器被解释成词语,词语通过语法分析器构建成节点,最后节点组合成dom树。
1. 字节 —> 字符收到字节流之后,解释器会根据网页内容所使用的编码格式,将字节流解析成对应的字符串。如果没有特别指定编码格式,直接进入下一步的词法分析。
2. 字符 —> 词语HTMLTokenizerHTMLTokenizer类负责词法解析。输入字符串,输出是一个个的词语。解释完成的词语会经过XSSAuditor安全验证,干嘛的呢?实质就是将一些可能会导致安全问题的词语过滤掉。只有通过安全验证的词语,才会继续下一步。
3. 词语 —> 节点HTMLTreebuilder类的construcTree由词语创建节点过程中,坑会遇到js代码。这就是为什么全局执行的js无法访问dom ...
Webkit系列:第一回(先验内容)
一些关于浏览器的先验内容
2005年苹果开源了自家的safari浏览器内核webkit,2008年,谷歌改造webkit为blink,开发出了chromium,最终推出chrome。
chrome是一个典型的多进程的架构,即chrome这么个应用,是由多个子进程组成的,具体包括如下:
浏览器进程: 负责管理除了页面显示的其他区域,也就是及页面地址栏那些东西,当然还包括书签等。
渲染进程: 该进程又称为内核,将请求资源转换为可视化(可听化)的图像结果,就是浏览器内核。渲染进程又有多个重要的子线程组成,
GUI线程: 浏览器拿到请求资源后,有一步操作就是,根据html和css文件分别生成dom树和样式树,然后生成渲染树和布局树,这部分的工作,就是gui线程负责实现的。
JS线程:又称为js主线程,就是执行js代码的。
合成器线程:该线程获得布局树后,通过栅格化确定一帧的每个像素点数据,最终交由GPU进程处理。
定时器线程: 如果当js主线程执行代码时,遇到settimeout和setInterval两定时器的时候,主线程会把定时器函数扔给定时器线程处理,自己继续往下执行。定时线程等待设 ...
React系列:第九回(concurrentmode、fiber)
本文介绍,react快速渲染的基石:concurrentmode、fiber上一代版本存在的问题在第一回中,我们通过手撕myCreateElement和myRender实现了基本的功能,但是仔细观察下之前写的render,是否存在什么问题?
const myRender = (element, container) => {
const dom = element.type === 'text'? document.createTextNode(element.props.nodeValue): document.createElement(element.type)
Object.keys(element.props).filter((item) => item !== 'children').forEach((item) => dom[item] = element.props[item])
element?.props?.children?.forEach((child) => myRender(child, dom))
container.append ...
区块链文档0
本系列文章,将围绕实践中的项目,用于记录开发过程中,遇到的那些个事儿本项目也是一个极具挑战性的任务:基于opensuim开发一套前端代码编辑器,没错,就是要把vscode搬到页面上。我们的最终目的, 是为区块链开发者提供一整套在线敲代码的集成环境,渐进式提供各种链。
在正式内容开始前,先见到介绍些区块链相关的背景知识。
1.什么是区块链?区块链最好的解释就是一个公共数据库公链:任何人都可以参与的区块链,如比特币和以太坊。联盟链:需要得到许可的参与者才能加入的区块链,如R3 Corda和Hyperledger Fabric。私有链:仅允许特定组织或个人参与的区块链。
去中心化是基于P2P网络的,没有一台机器作为中心化的服务器的功能,网络中的每一台电脑都是平等的,任何一台掉线、宕机,都不会影响整个网络继续运行。
定量法币通常与背后的黄金或者所谓的GDP挂钩,算是相对固定(经济低迷时的过量发行暂且别考虑了)。加密货币,可以算作绝对的固定数量,或者少量的增发(可以弥补一些丢失的币等),防止通货膨胀。
加密
上面就是加密货币的三个典型特征,第一点借助p2p网络实现没问题,但是后面的二三两点存 ...
Https的加密过程
本文介绍目下的https协议,是如何进行加密的很久很久以前,数据都是明文传输的,这样的方式毫无安全可见。中间人可以随意获取甚至篡改数据,那现在的什么网上购物、支付等几无可能。后来就出现了https,在http的基础之上,加了一个安全套接层,它的作用,就是用来对数据进行加密和解密。熟悉osi七层模型的同学都很清楚,http是应用层协议,下面还有传输层的tcp和网络层ip。加密解密的操作,可以看作介于应用层和传输层之间,也就是货物上路之前的和卸货时的时间点。
对称加密和非对称加密形象的比喻,对称加密就是一把钥匙,既能加密,也能解密。而非对称加密则是,加密一把钥匙,解密一把钥匙。
加密策略的演进历程
纯对称加密发送请求前,浏览器会给s端发送加密相关的东西: 加密套件和加密列表.前者就是加密的具体方法,后者指的是浏览器能够支持的哪些方法。s端收到东西之后也会给c端返回数据。这里可以浅显的理解为使用的加密方式,也就是对称加密的钥匙。这样,浏览器之后发送的所有请求,都会用这把钥匙进行加密,到了服务器端,再用这把钥匙进行解密。
缺点: 那把钥匙,在传输过程中,也是明文的,因此问题并未解决。
对 ...
canvas和svg渲染及其他
本文介绍下canvas和svg相关内容渲染层面在目前前端2d层面,图形化开发有两种方案:canvas和svg。借助它们都能帮我们绘制各种图形,但是两者底层原理完全不同。canvas本质就是批量绘制像素点,从dom结构看,他就是一个完整的dom节点,不管你在上面绘制了多少path,最终就是一个dom节点canvas。但是用svg则完全不同,svg绘制的path本身,就是一个个的dom节点。所以如果是海量数据,很显然,使用canvas批量绘制像素点的效率,远高于创建海量的dom节点。但是svg也有优点,因为是一个个的dom,所以支持原生事件(click/hover)、CSS 样式控制,交互开发成本低,且矢量图形缩放无失真。
性能考量-canvas有时候有些极端场景不可避免,比如Canvas 渲染 10 万条折线时出现卡顿,该如何优化?
视图渲染。这种手段的叫法有很多,什么脏矩阵、局部渲染等,但都是一个逻辑:只渲染视图范围内的数据。
数据抽稀。说白了就是减少数据点。比如2d图形开发,本质就是一个个的点组成的。那么一条线段可以用10000个点描述,也可以只用两个点描述(起始点)。这里有一些算 ...
前端缓存相关
谈到前端性能优化,缓存策略是必聊得。今天咱们就来扒一扒主要的两部分:强缓存和协商缓存。 以前我的理解就是:当我们需要向服务器请求资源时,浏览器首先会检查,是否命中强缓存。如果命中,则直接从缓存中拿资源,注意,此情况不需要像后端发送请求。如果没有命中,就会像后端真实发送请求,然后由后端判断,是否命中协商缓存。若命中,返回304,告诉前端资源未更新,可以用本地的,若没有命中,则找到对应资源返回,状态码通常200。上面的表述不能说不对,但是显然缺少细节。现在既然要来扒一扒,咱么就深入一下。
1. 强缓存:强缓存主要是通过http请求头中的Cache-Control和Expire两个字段控制。Expire是HTTP1.0标准下的字段,在这里我们可以忽略。我们重点来讨论的Cache-Control这个字段。Cache-Control是HTTP/1.1标准下的。 一般,我们会设置Cache-Control的值为“public, max-age=xxx”,表示在xxx秒内再次访问该资源,均使用本地的缓存,不再向服务器发起请求。 为什么指定缓存过期时间需要两个字段呢? 因为有 ...
算法:动态规划
本文介绍一种经典的算法思想:动态规划
官方文邹邹定义:将一个问题拆成几个子问题,分别求解这些子问题,即可推断出大问题的解。个人理解:未来取决于当下,脱钩于过去使用DP的场景:能将大问题拆成几个小问题,且满足无后效性、最优子结构性质。
经典算法必须有经典场景:斐波那契数列。这种数列的一个最大特点: 初始值:f(1) = 1, f(2) = 1,之后的每一项都是前两项的和。所以f(3) = f(1) + f(2) = 2….
1. 爬楼梯爬楼梯的方式有两种,一次一级或者两级,那么跳到n级,有多少种跳法?实际就是一个斐波拉契数列,f(1) = 1, f(2) = 1…
const climbStairs = function(n) {
if (n <= 1) return 1
const f = [1,2]
for (let i = 2; i < n; i++) {
f[i] = f[i-1] + f[i-2]
}
return f ...
性能的考量:第五回(长任务)
关于性能问题,我们前文介绍过了八股文篇、实战版本以及canvas性能相关的实操。今天,我们结合前文介绍过的google的performance工具,来更加深入的聊一聊。在web性能领域,有一个单独的单词long task,就是所谓的长任务。一般来讲,耗时超过50ms即可被认为长任务。这种长任务会导致什么结果呢?大佬解答:
If the user is attempting to interact with the page while a long task runs—or if an important rendering update needs to happen—the browser will be delayed in handling that work.
简言之:卡死你。
以目下的一个业务场景为例。该项目的某个页面加载耗时,长达6s。打开performance工具分析发现,符合长任务定义的操作,存在还不止一个,且单个耗时远超50ms,如下图所示:
针对上述的“long task”,我们怎么优化呢?
异步化任务
依据向主线程妥协的原则,有些场景下的一些任务,不 ...
Threejs系列:第一回
本文简单介绍threejs的基本内容。开宗明义three.js官方定义的三大要素:场景(scene)、相机(camera)、渲染器(render)。我觉得还得加上一个物体(内容)。本文以一个简单的球形案例带大家一起入个门。(基于vue2)
首先html骨架代码,很简单:
<template>
<div class="circleEarth-container flex-cc">
<div id="container" ref="container" class="container"></div>
</div>
</template>
JS完整代码
const container = this.$refs['container']
let scene = new Three.Scene()
const geometry = new Three.SphereBufferGeometry(60, 40, 40)
const material = new Three.MeshStanda ...
