mirror of
https://github.com/NohamR/knowledge-kit.git
synced 2026-05-25 04:17:17 +00:00
update: image source
This commit is contained in:
BIN
Chapter2 - Web FrontEnd/.DS_Store
vendored
Normal file
BIN
Chapter2 - Web FrontEnd/.DS_Store
vendored
Normal file
Binary file not shown.
@@ -5,7 +5,7 @@
|
||||
从安全性、高性能等原因出发,目前浏览器已经是多进程架构模式,至于演进历史,本文不再展开,感兴趣的可以查看这篇[“Electron” 一个可圈可点的 PC 多端融合方案]()文章。
|
||||
|
||||
现在的架构设计如下:
|
||||

|
||||

|
||||
|
||||
一个页面最少包括:1个网络进程、1个浏览器进程、1个 GPU 进程、多个渲染进程、多个插件进程
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
|
||||
熟悉其他系统设计的同学可能会立马想到用**队列**来解决问题。浏览器对这个 case 也采用队列,叫做事件队列。
|
||||
|
||||
<img src="./../assets/JSMainThreadEventLoop.png" style="zoom:30%;">
|
||||
<img src="https://github.com/FantasticLBP/knowledge-kit/raw/master/assets/JSMainThreadEventLoop.png" style="zoom:30%;">
|
||||
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
|
||||
应对这种情况,浏览器采用异步的设计来解决,如下图
|
||||
|
||||
<img src="./../assets/JSEventloop.png" style="zoom:40%;">
|
||||
<img src="https://github.com/FantasticLBP/knowledge-kit/raw/master/assets/JSEventloop.png" style="zoom:40%;">
|
||||
|
||||
使用异步的方案,可以使得主线程不等待、不阻塞,高效有序的执行逻辑。
|
||||
|
||||
@@ -148,15 +148,15 @@
|
||||
|
||||
T0 时刻:最开始的时候,主线程没有任务任务需要执行。但是主线程告诉交互线程,你需要监听用户的点击事件,点击后需要执行 callback
|
||||
|
||||
<img src="./../assets/JS-UIClickLag1.png" style="zoom:60%;">
|
||||
<img src="https://github.com/FantasticLBP/knowledge-kit/raw/master/assets/JS-UIClickLag1.png" style="zoom:60%;">
|
||||
|
||||
T1时刻:当用户点击后,交互线程会把 callback 封装成一个任务,添加到事件循环队列的尾部。此时主线程依旧没有任务,所以主线程事件循环将被唤醒,从事件队列的头部取出一个任务去执行。大的一个任务里包含2个子事件:修改 DOM 和 延迟3秒。修改 DOM 这句指令执行后,浏览器要想看的见,需要内部会产生一个绘制任务(硬件设备显示图形的画家算法)。绘制任务被添加到事件队列尾部后,立马执行延迟3秒的事件。
|
||||
|
||||
<img src="./../assets/JS-UIClickLag2.png" style="zoom:60%;">
|
||||
<img src="https://github.com/FantasticLBP/knowledge-kit/raw/master/assets/JS-UIClickLag2.png" style="zoom:60%;">
|
||||
|
||||
T2时刻:到达T2时刻后,主线程又空了,此时从事件队列中读取绘制任务。进而去显示出 DOM 文本修改后的结果(但此时前面已经等待了3秒钟,所以体感上会有一种卡顿的现象)
|
||||
|
||||
<img src="./../assets/JS-UIClickLag3.png" style="zoom:60%;">
|
||||
<img src="https://github.com/FantasticLBP/knowledge-kit/raw/master/assets/JS-UIClickLag3.png" style="zoom:60%;">
|
||||
|
||||
|
||||
|
||||
@@ -198,7 +198,7 @@ T2时刻:到达T2时刻后,主线程又空了,此时从事件队列中读
|
||||
|
||||
|
||||
|
||||
QA:JS 计时器准吗?
|
||||
## JS 计时器准吗?
|
||||
|
||||
不准。存在以下几个原因:
|
||||
|
||||
@@ -208,14 +208,15 @@ QA:JS 计时器准吗?
|
||||
- 受事件循环的影响,计时器的回调函数只能在主线程空闲时运行,因此又带来了偏差
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 计算机的时间
|
||||
没有时间,我们的生活将无序,无法度量。计算机更是如此,比如纳秒级的运算,那么计算机到底是如何感知时间的呢?
|
||||
计算机依靠**晶振**(全称是石英晶体振荡器),是一种高精度、高稳定度的振荡器。位置一般在主板上,晶振为系统提供很稳定的脉冲信号,一秒内产生的脉冲次数也被称为系统时钟频率。一个标准的脉冲信号如下:
|
||||

|
||||
几个概念:
|
||||
- 时钟周期:这里的时钟就是晶振,也就是晶振周期/振荡周期。是计算机的最小时间单元,其他周期只能是它的倍数
|
||||
- 机器周期性:既生瑜何生亮?时钟周期太小了,小到表述很多东西不够方便。到了 CPU 操作层面来说时钟周期不好用,类似人民币,虽然早期有1分钱,但某个商品价格比较大,需要1238902分,咋感觉这个单位不那么好用了,所以设计了100百元这个度量单位。一个机器周期等于多个时钟周期,它是 CPU 的一个基本操作时间单元,比如:取指、译码、存储器读/写、运算等等操作
|
||||
- 指令周期:是 CPU 完成一条指令的时间,又称为提取-执行周期(fetch-and-execute cycle),是指 CPU 要执行一条指令经过的步骤,由若干机器周期组成。不同的机器分解指令周期的方式不同。
|
||||
- 总线周期:它是 CPU 操作指令设备的时间,由于存储器和 I/O 端口是挂接在总线上的,对它们的访问是通过总线实现的。通常将进行一次访问所需时间称为一个总线周期。这种访问速度较慢,因硬件设备发展的原因,各个设备的工作频率无法同步(周期不一致),甚至相差好几个数量级,CPU 很快,硬盘很慢,大家又需要协同工作,所以出现了**分频**的概念。将高频信号变成低频信号。
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -29,11 +29,11 @@ GUI 架构:过程化绘制(drawLine、drawRect)-> 面向对象抽象时代
|
||||
|
||||
3天时间写了个 PC 端应用程序。先看看结果吧
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ npm install && npm start
|
||||
```
|
||||
|
||||
简单介绍下 Demo 工程,工程目录如下所示
|
||||

|
||||

|
||||
|
||||
在终端执行 `npm start` 执行的是 package.json 中的 `scripts` 节点下的 start 命令,也就是 `Electron .`,`.` 代表执行 main.js 中的逻辑。
|
||||
|
||||
@@ -159,7 +159,7 @@ Electron 分为**渲染进程和主进程**。和 Native 中的概念不一样
|
||||
|
||||
单进程浏览器指的是浏览器的所有功能模块都是运行在同一个进程里的,这些模块包括网络、插件、Javascript 运行环境、渲染引擎和页面等。如此复杂的功能都在一个进程内运行,所以导致浏览器出现不稳定、不安全、不流畅等问题。
|
||||
|
||||

|
||||

|
||||
|
||||
早在2007年之前,市面上的浏览器都是单进程架构。
|
||||
|
||||
@@ -194,7 +194,7 @@ Electron 分为**渲染进程和主进程**。和 Native 中的概念不一样
|
||||
|
||||
#### 1.2 早期多进程架构浏览器
|
||||
|
||||

|
||||

|
||||
|
||||
上图2008年 Chrome 发布时的进程架构图。可以看出 Chrome 的页面是运行在单独的渲染进程中,同时页面的插件也是运行在单独的插件进行中的,进程之间通过 IPC 进行通信。
|
||||
|
||||
@@ -218,7 +218,7 @@ Electron 分为**渲染进程和主进程**。和 Native 中的概念不一样
|
||||
|
||||
Chrome 团队不断发展,目前架构有了较新变化,最新 Chrome 架构图如下所示
|
||||
|
||||

|
||||

|
||||
|
||||
最新 Chrome 浏览器包括:1个网络进程、1个浏览器进程、1个 GPU 进程、多个渲染进程、多个插件进程。
|
||||
|
||||
@@ -247,7 +247,7 @@ Chrome 团队一直在寻求新的弹性方案,既可以解决资源占用较
|
||||
|
||||
Chrome 最终把 UI、数据库、文件、设备、网络等模块重构为基础服务。下图是 “Chrome 面向服务的架构”的进程模型图
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
@@ -257,7 +257,7 @@ Chrome 最终把 UI、数据库、文件、设备、网络等模块重构为基
|
||||
|
||||
Chrome 提供灵活的弹性架构,在强大性能设备上会以多进程的方式运行基础服务,但是在设备资源受限的情况下,Chrome 会将很多服务整合到一个进程中,从而节省内存占用。
|
||||
|
||||

|
||||

|
||||
|
||||
#### 1.5 小实验
|
||||
|
||||
@@ -273,7 +273,7 @@ Chrome 提供灵活的弹性架构,在强大性能设备上会以多进程的
|
||||
|
||||
实验现象:
|
||||
|
||||

|
||||

|
||||
|
||||
实验结论:
|
||||
|
||||
@@ -310,7 +310,7 @@ Chrome 的默认策略是,每个标签对应一个渲染进程。但是如果
|
||||
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
@@ -331,7 +331,7 @@ Chrome 的默认策略是,每个标签对应一个渲染进程。但是如果
|
||||
|
||||
### 2. Electron 架构
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
@@ -353,7 +353,7 @@ Electron 架构和 Chromium 架构类似,也是具有1个主进程和多个渲
|
||||
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
上图描述了 Node.js 如何融入到 Chromium 中。描述下原理
|
||||
|
||||
@@ -380,7 +380,7 @@ Electron 架构和 Chromium 架构类似,也是具有1个主进程和多个渲
|
||||
|
||||
工程采用 Electron + Vue 技术,下面截图 Vue-devtools 很方便查看 Vue 组件层级等 Vue 相关的调试
|
||||
|
||||

|
||||

|
||||
|
||||
### 2. 主进程调试方式
|
||||
|
||||
@@ -395,10 +395,10 @@ Electron 架构和 Chromium 架构类似,也是具有1个主进程和多个渲
|
||||
```
|
||||
- 然后打开浏览器,在地址栏输入 `chrome://inspect`
|
||||
- 点击 `configure`,在弹出的面板中填写需要调试的端口信息
|
||||
- 
|
||||
- 
|
||||
- 重新开启服务 `npm start`,在 chrome inspect 面板的 `Target` 节点中选择需要调试的页面
|
||||
- 在面板中可以看到主进程执行的 `main.js`。可以加断点进行调试
|
||||

|
||||

|
||||
|
||||
方法二:利用 VS Code 调试 Electron 主进程。
|
||||
|
||||
@@ -428,7 +428,7 @@ Electron 架构和 Chromium 架构类似,也是具有1个主进程和多个渲
|
||||
|
||||
- 在调试模点击绿色小三角,会运行程序,可以添加断点信息。整体界面如下所示。可以单步调试、可以暂停、鼠标移上去可以看到对象的各种信息。
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
@@ -438,7 +438,7 @@ Electron 的渲染进程中的代码改变了,使用 Command + R 可以刷新
|
||||
|
||||
Webpack 有一个 api: `watch-run`,可以针对代码文件检测,有变化则 Restart
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
@@ -527,7 +527,7 @@ Electron 官方给出了解决方案 Squirrel,基于 Squirrel 框架完成的
|
||||
|
||||
9. Electron 多窗口与单窗口应用区别
|
||||
|
||||

|
||||

|
||||
|
||||
10. 知道 Electron 开发原理,所以大部分时间是在写前端代码。所以根据团队技术沉淀、选择对应的前端框架,比如 Vue、React、Angular。
|
||||
|
||||
@@ -535,7 +535,7 @@ Electron 官方给出了解决方案 Squirrel,基于 Squirrel 框架完成的
|
||||
|
||||
12. Electron 和 Web 开发相比,各自有侧重点
|
||||
|
||||

|
||||

|
||||
|
||||
13. 有些人开发 Electron 应用可能不喜欢 [electron-vue](https://github.com/SimulatedGREG/electron-vue) 这样的工具,喜欢自己自定义。假如自己利用 Vue 或者 React 开发的,开发过网页的同学都会习惯使用 Vue-devtools、React-devtools。所以在选用 Vue 或 React 后,习惯使用强大的 Vue-devtools、React-devtools 来查看 State、Action、Redux、Vuex、组件层级树等。
|
||||
|
||||
@@ -591,13 +591,13 @@ node --cpu-prof --heap-prof -e "require('request’)”“
|
||||
|
||||
### 1. 构建
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
### 2. 工程解耦
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
@@ -605,7 +605,7 @@ node --cpu-prof --heap-prof -e "require('request’)”“
|
||||
|
||||
Electron 提供的 crash 信息进行包装。
|
||||
|
||||

|
||||

|
||||
|
||||
```js
|
||||
import { BrowserWindow, app, dialog} from 'Electron';
|
||||
|
||||
@@ -43,7 +43,7 @@ QA:
|
||||
|
||||
为了提高解析效率,浏览器会启动一个预解析器率先下载和解析 CSS
|
||||
|
||||
<img src="https://github.com/FantasticLBP/knowledge-kit/raw/master/assets/HTMLParse-CSSPreload.png" style="zoom:20%;">
|
||||
<img src="https://github.com/FantasticLBP/knowledge-kit/raw/master/assets/HTMLParse-CSSPreLoad.png" style="zoom:20%;">
|
||||
|
||||
|
||||
|
||||
@@ -261,7 +261,7 @@ p {
|
||||
|
||||
都处于页面作者样式表中,选择器的权重也相同,但根据所处位置的不同,下面的样式声明会覆盖上面的值,最终采用 #0000ff。
|
||||
|
||||
<img src="https://github.com/FantasticLBP/knowledge-kit/raw/master/assets/CssStylePositionPriority.png" style="zoom:25%;">
|
||||
<img src="https://github.com/FantasticLBP/knowledge-kit/raw/master/assets/CSSStylePositionPriority.png" style="zoom:25%;">
|
||||
|
||||
样式声明冲突的情况解决了
|
||||
|
||||
@@ -284,7 +284,7 @@ p {
|
||||
|
||||
只对类名为 container color 进行了设置,针对 p 标签没有任何的设置,但由于 color 可以继承,所以 p 就从最近的 div 继承了颜色。
|
||||
|
||||
<img src="https://github.com/FantasticLBP/knowledge-kit/raw/master/assets/CssStyleInherited.png" style="zoom:25%;">
|
||||
<img src="https://github.com/FantasticLBP/knowledge-kit/raw/master/assets/CSSStyleInherited.png" style="zoom:25%;">
|
||||
|
||||
看另一个现象
|
||||
|
||||
@@ -302,7 +302,7 @@ p {
|
||||
</div>
|
||||
```
|
||||
|
||||
<img src="https://github.com/FantasticLBP/knowledge-kit/raw/master/assets/CssStyleDoubleInherited.png" style="zoom:25%;">
|
||||
<img src="https://github.com/FantasticLBP/knowledge-kit/raw/master/assets/CSSStyleDoubleInherited.png" style="zoom:25%;">
|
||||
|
||||
这里继承了 container、innerContainer 2个的属性值,说了继承会选择更近的一个,innerContainer 胜出。
|
||||
|
||||
@@ -318,7 +318,7 @@ p {
|
||||
</div>
|
||||
```
|
||||
|
||||
<img src="https://github.com/FantasticLBP/knowledge-kit/raw/master/assets/CssStyleDefaultValue.png" style="zoom:25%;">
|
||||
<img src="https://github.com/FantasticLBP/knowledge-kit/raw/master/assets/CSSStyleDefaultValue.png" style="zoom:25%;">
|
||||
|
||||
任何一个元素要在浏览器上渲染出来,必须具备所有的 css 属性值,但很多属性我们没有去设置,用户代理样式表中也没有设置,也无法从继承中拿到,因此最终都是使用默认值的。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user