程序开发如火如荼,如果你是程序员,你还不懂小程序的开发,恐怕会被同行认为太LOW了吧!不过,新入行小程序开发者确实会被新的名词搞得一头雾水。
比如JavaScript不是在浏览器端运行吗,怎么还可以写服务器端的程序,NodeJS是干啥的,V8和NodeJS有啥区别,什么NMP命令,它是干嘛的,想把这些东东的本质看透吗,我们来剖析一下吧。
JavaScript
JavaScript是一种属于网络的解释性脚本语言,已经被广泛用于Web应用开发,用来给HTML网页增加动态功能,为用户提供更流畅美观的浏览效果。通常JavaScript脚本是通过嵌入在HTML中来实现自身的功能的。它的解释器被称为JavaScript引擎,为浏览器的一部分。
V8引擎
V8引擎就是JavaScript运行的解释器,是JavaScript一种引擎。它是Google开发的,作为chrome浏览器的JavaScript执行解释器,性能十分优秀,被广泛的使用。
NodeJS
在2009年的欧洲JavaScript大会上, 年轻程序员Ryan Dahl展示了他正在从事的一个项目,该项目是一个集成了Google V8 JavaScript引擎、事件循环和底层I/O应用编程接口(Application Programming Interface, API)的平台。
与其他服务器端的JavaScript平台不同,Dahl的平台中所有I/O原语都是事件驱动的,除此以外别无他途。借助JavaScript的影响力和易用性,Dahl的项目使得编写基于事件驱动的服务器端应用程序的任务由难变易, 因此,该项目受到了热烈欢迎, 并且它的发展、普及和被接受程度都是前所未有的。这个项目被命名为NodeJS。NodeJS不单单是JavaScript引擎,JavaScript引擎只是它的一个子集。
NodeJS中的JavaScript引擎没有BOM、DOM。NodeJS是JavaScript的一种运行环境,是对Google V8引擎进行的封装。是一个服务器端的JavaScript的解释器。
nmp管理工具
除了使用NodeJS语言特性及核心函数,我们还需要使用一些已经编写好的优秀的第三方库, 这也是为什么大多数编程平台都具有一个系统用来下载、 安装和管理第三方模块的原因。 在NodeJS中这个系统被称为NodeJS包管理器(NodePackage Manager, NPM)。NPM是三位一体的系统第三方包库、管理计算机中安装的包的机制以及定义包依赖关系的标准。NPM提供了一种公共注册服务,它包含了程序员在NPM中发布的所有包,NPM还提供了一个命令行工具用来下载、安装和管理这些包。
在早期,NPM和NodeJS是要分别独立安装的,但是从0.6.0版开始,NPM就己经包含在Node的安装包中。NodeJS中含有NPM。
css即时按需的原子化CSS引擎有何作用?例如在这里给它一个相关的dlass,最终它生成了一个CSS代码,就是下面相关的样式了。也就是说可以在html代码中直接书写样式。
例如在这里,想让一段文本向右移动,只需给它一个right的样式即可。例如再给它添加一个颜色red,就变成红色了。对于不熟悉样式的人,可以参考这里的文档。在这里,可以搜索相关样式并查看效果。
例如W4是一个单位,默认使用R、e m作为单位。如果项目通常使用PX,可以在这里进行转换,并提供相关配置和图标、字体等。可以在常用的Vite项目中进行整合。首先安装依赖,然后在Vite配置文件中引入,在插件中声明figl,然后导入CSS即可使用。
当然,官方文档是英文版的,因此许多人会参考Windi CSS文档进行学习。这是一个非常聪明的方法,因为它可以通过Uno CSS减轻样式代码,提高生产效率。
可能已经听说过Project Quantum ...它是Firefox的内部部件的重大改写,使Firefox快速。我们正在从我们的实验浏览器Servo中进行部分交换,并对引擎的其他部分进行了大量改进。
该项目已经与喷气式飞机仍在飞行中替换喷气发动机相比较。我们正在按组件进行更改,以便在每个组件准备就绪后,您可以在Firefox中看到效果。
而Servo的第一个主要组件 - 名为Quantum CSS(以前称为Stylo)的新CSS引擎 - 现在可以在我们的Nightly版本中进行测试。您可以通过转到about:config
并设置layout.css.servo.enabled
为true 来确保它已打开。
这款新引擎将来自四个不同浏览器的最先进的创新融合在一起,以创建一个新的超级CSS引擎。
它利用了现代硬件,并行化了机器中所有内核的工作。这意味着它最多可以运行2或4甚至18倍。
除此之外,它结合了来自其他浏览器的现有最新优化。所以即使没有并行运行,它仍然是一个快速的CSS引擎。
但是什么是CSS引擎呢?首先,我们来看看CSS引擎,以及它如何适应浏览器的其余部分。那么我们可以看看Quantum CSS如何使它更快。
什么是CSS引擎?
CSS引擎是浏览器渲染引擎的一部分。渲染引擎采用网站的HTML和CSS文件,并将其转换为屏幕上的像素。
每个浏览器都有一个渲染引擎。在Chrome中,它叫做Blink。在Edge中,它被称为EdgeHTML。在Safari中,它被称为WebKit。在Firefox中,它被称为Gecko。
要从文件到像素,所有这些渲染引擎基本上都做同样的事情:
将文件解析为浏览器可以理解的对象,包括DOM。在这一点上,DOM知道页面的结构。它知道元素之间的父/子关系。不知道这些元素应该是什么样的。
找出这些元素应该是什么样的。对于每个DOM节点,CSS引擎都会确定哪些CSS规则适用。然后,它会为该DOM节点的每个CSS属性确定值。
绘出每个节点的尺寸及其在屏幕上的位置。将为屏幕上显示的每个东西创建框。这些方框不仅仅代表DOM节点,还可以为DOM节点内的东西,如文本行。
画不同的盒子。这可能发生在多层。我想起了这个像老式的手绘动画,带有洋葱的纸层。这样就可以改变一个层,而不必在其他层上重绘某些东西。
拿这些不同的绘图层,应用任何只有合成器的属性,如transforms,并将它们变成一个图像。这基本上就像是将层叠在一起的图片。此图像将在屏幕上呈现。
这意味着当它开始计算样式时,CSS引擎有两件事情:
一个DOM树
风格规则清单
它逐个浏览每个DOM节点,并计算出该DOM节点的样式。作为其中的一部分,它为DOM节点提供了每个CSS属性的值,即使样式表未声明该属性的值。
我想像这样像一个人通过填写一个表单。他们需要为每个DOM节点填写这些表单之一。而对于每个表格领域,他们需要有一个答案。
要做到这一点,CSS引擎需要做两件事情:
找出哪些规则适用于节点 - aka 选择器匹配
使用父级值或默认值(也称为级联)填充任何缺少的值
选择器匹配
对于此步骤,我们将添加与DOM节点匹配的任何规则到列表。因为多个规则可以匹配,所以同一属性可能有多个声明。
此外,浏览器本身还添加了一些默认的CSS(称为用户代理样式表)。CSS引擎知道要选择哪个值?
这就是特定性规则的出现。CSS引擎基本上创建一个电子表格。然后它根据不同的列对声明进行排序。
具有最高特异性的规则胜出。所以基于这个电子表格,CSS引擎填写了它可以的值。
对于其余的,我们将使用级联。
级联
级联使得CSS易于编写和维护。因为级联,可以设置color
在机身性能和知道该文本p
,并span
和li
元素都将使用该颜色(除非你有一个更具体的覆盖)。
为此,CSS引擎会查看其表单上的空白框。如果该属性默认继承,那么CSS引擎将向上爬树,以查看其中一个祖先是否具有值。如果没有一个祖先有一个值,或者该属性不继承,它将获得一个默认值。
所以现在所有的样式都已经为这个DOM节点计算了。
一个sidenote:风格结构共享
我向你展示的形式有点虚伪。CSS有数以百计的属性。如果CSS引擎持有每个DOM节点的每个属性的值,它将很快耗尽内存。
相反,引擎通常会做一些所谓的样式结构共享。它们通常在一起被称为样式结构的不同对象中存储数据(如字体属性)。然后,代替在同一对象中拥有所有属性,计算的样式对象只有指针。对于每个类别,都有一个指向具有该DOM节点正确值的样式结构的指针。
这将节省内存和时间。具有类似属性的节点(如兄弟姐妹)可以指向与它们共享的属性相同的结构体。并且因为许多属性都被继承,所以祖先可以与没有指定自己的覆盖的任何后代共享一个结构体。
现在,我们如何做到这一点呢?
那么当你没有优化它时,这就是什么样的计算。
这里有很多工作。它不仅仅需要在第一页的加载中发生。当用户与页面进行交互,将鼠标悬停在元素上或对DOM进行更改时,会重复出现,从而触发重新启动。
这意味着CSS样式计算是优化的最佳选择...而浏览器已经测试出不同的策略,以优化它在过去20年。什么Quantum CSS做的是从不同的引擎中充分利用这些策略,并结合它们来创建一个超快的新引擎。
所以我们来看看这些工作如何共同的细节。
并行运行
Servo项目(Quantum CSS来自)是一个实验浏览器,它试图并行化渲染网页的所有不同部分。这意味着什么?
一台电脑就像一只大脑。有一部分做这个想法(ALU)。在这个附近,有一些短期记忆(寄存器)。这些在CPU上组合在一起。那么长期的内存是RAM。
早期的电脑一次只能用这种CPU来思考一件事情。但是在过去十年中,CPU已经转移到拥有多个ALU和寄存器,分组在一起。这意味着CPU可以一次思考多个东西 - 并行。
Quantum CSS通过分散不同核心上的不同DOM节点的样式计算来利用计算机的最新功能。
这似乎是一件容易的事情,只需拆分树的分支,并在不同的核心上进行。这实际上比这更难,原因很多。一个原因是DOM树往往是不均匀的。这意味着一个核心将比其他核心更多的工作要做。
为了平衡工作,Quantum CSS使用了一种称为工作窃取的技术。正在处理DOM节点时,代码将其直接子代并将其分解为1个或多个“工作单元”。这些工作单位放在队列中。
当一个核心完成了队列中的工作时,它可以在其他队列中查找更多的工作。这意味着我们可以平均分配工作,而不用花时间去走树,找出如何提前平衡。
在大多数浏览器中,很难得到这个权利。并行是一个已知的困难问题,CSS引擎非常复杂。它也坐在渲染引擎的另外两个最复杂的部分之间 - DOM和布局。所以很容易引入一个bug,并行性可能会导致很难追踪的错误,称为数据竞争。我在另一篇文章中更多地解释了这些错误。
如果您接受来自数百或数千名工程师的贡献,您如何并行编程而不用担心?这就是我们有Rust的。
使用Rust,您可以静态地验证您没有数据竞争。这意味着您只需不要让他们进入您的代码,避免棘手的调试错误。编译器不会让你这样做。我将在以后的文章中写下更多关于这一点。在此期间,您可以观看关于Rust中的并行性的介绍视频,或者更深入地讨论工作窃取。
有了这个CSS样式计算就会变成一个令人尴尬的并行问题 - 几乎没有什么可以让你有效地并行运行它。这意味着我们可以接近线性加速。如果您的机器上有4个内核,那么它的运行速度将提高近4倍。
用规则树加速重新开始
对于每个DOM节点,CSS引擎需要完成所有规则以进行选择器匹配。对于大多数节点,这种匹配可能不会很频繁地变化。例如,如果用户将鼠标悬停在父项上,则与之匹配的规则可能会更改。我们仍然需要重新计算其后代的样式来处理属性继承,但是与这些后代匹配的规则可能不会改变。
如果我们可以记下哪些规则与这些后代相匹配,那么这将是很好的,所以我们不必再为它们进行选择器匹配,这就是Firefox以前的CSS引擎借来的规则树。
CSS引擎将通过查找匹配的选择器的过程,然后通过特异性对它们进行排序。从此,它创建了一个链接的规则列表。
该列表将被添加到树中。
CSS引擎尝试将树中的分支数保持在最小。为此,它将尽可能地重用一个分支。
如果列表中的大多数选择器与现有分支相同,则它将遵循相同的路径。但是它可能会到达列表中的下一个规则不在树的这个分支中。只有在这一点上它才会添加一个新的分支。
DOM节点将获得指向最后插入的规则的指针(在本示例中为div#warning
规则)。这是最具体的一个。
在restyle上,引擎会快速检查以查看父母的更改是否可能改变与孩子相匹配的规则。如果没有,则对于任何后代,引擎可以跟随后代节点上的指针来获得该规则。从那里,它可以将树跟随到根,以获得匹配规则的完整列表,从最具体到最不具体。这意味着它可以完全跳过选择器匹配和排序。
因此,这有助于减少重建期间所需的工作。但是,在初始设计时,还是有很多工作。如果您有10,000个节点,您仍然需要选择器匹配10,000次。但还有另一种加速方式。
加快样式共享缓存的初始渲染(和级联)
想想一个具有数千个节点的页面。许多节点将匹配相同的规则。例如,想想一个漫长的维基百科页面...主要内容区域中的段落应该完全匹配完全相同的规则,并且具有完全相同的计算样式。
如果没有优化,则CSS引擎必须单独匹配每个段落的选择器和计算样式。但是,如果有一种方式来证明样式将从段落到段落相同,则引擎可以只做一次工作,并将每个段落节点指向相同的计算方式。
这就是Safari和Chrome浏览器启发的风格共享缓存。完成处理节点后,将计算的样式放入缓存中。然后,在开始下一个节点的计算样式之前,它会运行一些检查来查看是否可以使用缓存中的某些内容。
这些支票是:
2节点是否具有相同的ids,类等?如果是这样,那么他们会匹配相同的规则。
对于任何不是基于选择器的内联样式,例如,节点是否具有相同的值?如果是这样,那么上面的规则也不会被覆盖,也不会被同样的覆盖。
父母双方指向相同的计算样式对象吗?如果是这样,那么继承的值也将是一样的。
这些检查一开始就在早期的风格共享缓存中。但是还有很多其他样式可能不匹配的小案例。例如,如果CSS规则使用:first-child
选择器,则两个段落可能不匹配,即使上面的检查表明它们应该是。
在WebKit和Blink中,样式共享缓存将在这些情况下放弃,而不使用缓存。随着越来越多的网站使用这些现代选择器,优化越来越有用,所以Blink团队最近删除了它。但事实证明,风格共享缓存有一种方法来跟上这些变化。
在Quantum CSS中,我们收集所有这些奇怪的选择器,并检查它们是否适用于DOM节点。然后我们将答案存储为1和0。如果两个元素具有相同的一个和零个,我们知道它们绝对匹配。
如果DOM节点可以共享已经计算的样式,则可以跳过几乎所有的工作。因为页面通常具有多个具有相同样式的DOM节点,所以这种风格共享缓存可以节省内存并且还能够加快速度。
*请认真填写需求信息,我们会在24小时内与您取得联系。