浏览器模块

浏览器模块
进程是 CPU 资源分配的最小单位
线程是 CPU 调度的最小单位

对于操作系统来说,一个任务就是一个进程,比如打开一个浏览器就是启动了一个浏览器进程,打开一个 Word 就启动了一个 Word 进程。

在一个进程内部,要同时做多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程。
浏览器的多进程架构
在这里插入图片描述


主进程 Browser Process:
负责浏览器界面的显示与交互。各个页面的管理,创建和销毁其他进程。网络的资源管理、下载等。

第三方插件进程 Plugin Process
每种类型的插件对应一个进程,仅当使用该插件时才创建。

GPU 进程 GPU Process
最多只有一个,用于 3D 绘制等

渲染进程 Renderer Process
称为浏览器渲染进程或浏览器内核,内部是多线程的。主要负责页面渲染,脚本执行,事件处理等。 (本文重点分析)

渲染进程 (浏览器内核)
浏览器的渲染进程是多线程的,我们来看看它有哪些主要线程 :

  1. GUI (图形用户界面)渲染线程
  • 负责渲染浏览器界面,解析 HTML,CSS,构建 DOM 树和 RenderObject 树,布局和绘制等。

  • 当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行。

  • 注意,GUI 渲染线程与 JS 引擎线程是互斥的,当 JS 引擎执行时 GUI 线程会被挂起(相当于被冻结了),GUI 更新会被保存在一个队列中等到 JS 引擎空闲时立即被执行

  1. JS 引擎线程
  • Javascript 引擎,也称为 JS 内核,负责处理 Javascript 脚本程序。(例如 V8 引擎)

  • JS 引擎线程负责解析 Javascript 脚本,运行代码。

  • JS 引擎一直等待着任务队列中任务的到来,然后加以处理,一个 Tab 页(renderer 进程)中无论什么时候都只有一个 JS 线程在运行 JS 程序。

  • 注意,GUI 渲染线程与 JS 引擎线程是互斥的,所以如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞。

  1. 事件触发线程
  • 归属于浏览器而不是 JS 引擎,用来控制事件循环(可以理解,JS 引擎自己都忙不过来,需要浏览器另开线程协助)

  • 当 JS 引擎执行代码块如 setTimeOut 时(也可来自浏览器内核的其他线程,如鼠标点击、AJAX 异步请求等),会将对应任务添加到事件线程中

  • 当对应的事件符合触发条件被触发时,该线程会把事件添加到待处理队列的队尾,等待 JS 引擎的处理

  • 注意,由于 JS 的单线程关系,所以这些待处理队列中的事件都得排队等待 JS 引擎处理(当 JS 引擎空闲时才会去执行)

  1. 定时触发器线程
  • 传说中的 setInterval 与 setTimeout 所在线程

  • 浏览器定时计数器并不是由 JavaScript 引擎计数的,(因为 JavaScript 引擎是单线程的, 如果处于阻塞线程状态就会影响记计时的准确)

  • 因此通过单独线程来计时并触发定时(计时完毕后,添加到事件队列中,等待 JS 引擎空闲后执行)

  • 注意,W3C 在 HTML 标准中规定,规定要求 setTimeout 中低于 4ms 的时间间隔算为 4ms。

  1. 异步 http 请求线程
  • 在 XMLHttpRequest 连接后是通过浏览器新开一个线程请求。

  • 将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中。再由 JavaScript 引擎执行。

浏览器渲染流程

从输入 url 到页面加载发生了什么?
尽管Webkit与Gecko使用略微不同的术语,这个过程还是基本相同的,如下:
  1. 浏览器会将HTML解析成一个DOM树,DOM 树的构建过程是一个深度遍历过程:当前节点的所有子节点都构建好后才会去构建当前节点的下一个兄弟节点。
  2. 将CSS解析成 CSS Rule Tree 。
  3. 根据DOM树和CSSOM来构造 Rendering Tree。注意:Rendering Tree 渲染树并不等同于 DOM 树,因为一些像Header或display:none的东西就没必要放在渲染树中了。
  4. 有了Render Tree,浏览器已经能知道网页中有哪些节点、各个节点的CSS定义以及他们的从属关系。下一步操作称之为layout,顾名思义就是计算出每个节点在屏幕中的位置。
  5. 再下一步就是绘制,即遍历render树,并使用UI后端层绘制每个节点。

  • HTML被HTML解析器解析成DOM 树
  • css则被css解析器解析成CSSOM 树
  • 结合DOM树和CSSOM树,生成一棵渲染树(Render Tree)
  • 生成布局(flow),即将所有渲染树的所有节点进行平面合成
  • 将布局绘制(paint)在屏幕上
  1. 为什么 Javascript 要是单线程的 ?
    JavaScript的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?

——为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完
全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质

JavaScript语言的设计者意识到,这时主线程完全可以不管IO设备,挂起处于等待中的任务,先运行排在后面的任务。等到IO设备返回了结果,再回过头,把挂起的任务继续执行下去。

于是,所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入主线程、而进入”任务队列”(task queue)的任务,只有”任务队列”通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

  1. 为什么 JS 阻塞页面加载 ?
    由于 JavaScript 是可操纵 DOM 的,如果在修改这些元素属性同时渲染界面(即 JavaScript 线程和 UI 线程同时运行),那么渲染线程前后获得的元素数据就可能不一致了。
    因此为了防止渲染出现不可预期的结果,浏览器设置 GUI 渲染线程与 JavaScript 引擎为互斥的关系。
    当 JavaScript 引擎执行时 GUI 线程会被挂起,GUI 更新会被保存在一个队列中等到引擎线程空闲时立即被执行。
    从上面我们可以推理出,由于 GUI 渲染线程与 JavaScript 执行线程是互斥的关系,
    当浏览器在执行 JavaScript 程序的时候,GUI 渲染线程会被保存在一个队列中,直到 JS 程序执行完成,才会接着执行。
    因此如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。

  2. css 加载会造成阻塞吗 ?
    DOM 和 CSSOM 通常是并行构建的,所以 CSS 加载不会阻塞 DOM 的解析。
    然而,由于 Render Tree 是依赖于 DOM Tree 和 CSSOM Tree 的,
    所以他必须等待到 CSSOM Tree 构建完成,也就是 CSS 资源加载完成(或者 CSS 资源加载失败)后,才能开始渲染。
    因此,CSS 加载会阻塞 Dom 的渲染。

  3. DOMContentLoaded 与 load 的区别 ?
    1、onload事件
    onload事件所有的浏览器都支持,所以我们不需要什么兼容,只要通过调用
    window.onload = function(){

    }

2、DOMContentLoaded 事件
DOMContentLoaded不同的浏览器对其支持不同,所以在实现的时候我们需要做不同浏览器的兼容。
1)支持DOMContentLoaded事件的,就使用DOMContentLoaded事件;
2)IE6、IE7不支持DOMContentLoaded,但它支持onreadystatechange事件,该事件的目的是提供与文档或元素的加载状态有关的信息。
3) 更低的ie还有个特有的方法doScroll, 通过间隔调用:document.documentElement.doScroll(“left”);
可以检测DOM是否加载完成。 当页面未加载完成时,该方法会报错,直到doScroll不再报错时,就代表DOM加载完成了。该方法更接近DOMContentLoaded的实现。
写法:
function ready(fn){

if(document.addEventListener) {
    document.addEventListener('DOMContentLoaded', function() {
        document.removeEventListener('DOMContentLoaded',arguments.callee, false);
        fn();
    }, false);
} 

// 如果IE
else if(document.attachEvent) {
    // 确保当页面是在iframe中加载时,事件依旧会被安全触发
    document.attachEvent('onreadystatechange', function() {
        if(document.readyState == 'complete') {
            document.detachEvent('onreadystatechange', arguments.callee);
            fn();
        }
    });

    // 如果是IE且页面不在iframe中时,轮询调用doScroll 方法检测DOM是否加载完毕
    if(document.documentElement.doScroll && typeof window.frameElement === "undefined") {
        try{
            document.documentElement.doScroll('left');
        }
        catch(error){
            return setTimeout(arguments.callee, 20);
        };
        fn();
    }
}

};
addEventListener()是标准的绑定事件监听函数的方法,是W3C所支持的,Chrome、FireFox、Opera、Safari、IE9.0及其以上版本都支持该函数;但是,IE8.0及其以下版本不支持该方法,它使用attachEvent()来绑定事件监听函数。所以,这种绑定事件的方法必须要处理浏览器兼容问题。

谈谈浏览器的回流与重绘
回流必将引起重绘;
重绘不一定会引起回流;
回流可以看成页面架构发生改变;(比如dom销毁与重建,窗口大小发生改变,字体大小改变,激活css伪类(:hover),查询某些属性或者调用某些方法)
重绘:修改样式
重排优化建议:

  1. 分离读写操作
  2. 样式集中修改
  3. 缓存需要修改的DOM元素
  4. 尽量只修改position:absolute或fixed元素,对其他元素影响不大
  5. 动画开始GPU加速,translate使用3D变化

clientWidth、clientHeight、clientTop、clientLeft

offsetWidth、offsetHeight、offsetTop、offsetLeft

scrollWidth、scrollHeight、scrollTop、scrollLeft

scrollIntoView()、scrollIntoViewIfNeeded()

getComputedStyle()

getBoundingClientRect()

scrollTo()
clientWidth = width+左右padding
clientHeigh = height + 上下padding
clientTop = boder.top(上边框的宽度)
clientLeft = boder.left(左边框的宽度)
offsetWidth = width + 左右padding + 左右boder
offsetHeith = height + 上下padding + 上下boder
offsetTop:当前元素 上边框 外边缘 到 最近的已定位父级(offsetParent) 上边框 内边缘的 距离。如果父级都没有定位,则分别是到body 顶部 和左边的距离
offsetLeft:当前元素 左边框 外边缘 到 最近的已定位父级(offsetParent) 左边框内边缘的距离。如果父级都没有定位,则分别是到body 顶部 和左边的距离
scrollWidth:获取指定标签内容层的真实宽度(可视区域宽度+被隐藏区域宽度)。
scrollHeight:获取指定标签内容层的真实高度(可视区域高度+被隐藏区域高度)
scrollLeft:内容层左端 到 可视区域左端的距离.
scrollTop :内容层顶部 到 可视区域顶部的距离。

var scrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop;

window.addEventListener(‘scroll’, ()=>{
var scrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop;

});

一般我们都会说 “HTTP 是一个无状态的协议”
Cookie为了解决 HTTP 无状态导致的问题,后来出现了 Cookie。不过这样说可能会让你产生一些误解,首先无状态并不是不好,有优点,但也会导致一些问题。而 Cookie 的存在也不是为了解决通讯协议无状态的问题,只是为了解决客户端与服务端会话状态的问题,这个状态是指后端服务的状态而非通讯协议的状态。

它一般不超过 4KB 的小型文本数据,它由一个名称(Name)、一个值(Value)和其它几个用于控制 Cookie 有效期、安全性、使用范围的可选属性组成
存放:浏览器/本地
Cookie 的设置?

  1. 客户端发送 HTTP 请求到服务器
  2. 当服务器收到 HTTP 请求时,在响应头里面添加一个 Set-Cookie 字段
  3. 浏览器收到响应后保存下 Cookie
  4. 之后对该服务器每一次请求中都通过 Cookie 字段将 Cookie 信息发送给服务器
    属性:Name/Value(注意编码处理) Expires(设置有效时间)Max-Age(设置在 Cookie 失效之前需要经过的秒数)Domain(指定了 Cookie 可以送达的主机名)path/Secure属性/HTTPOnly

当 Expires 属性缺省时,表示是会话性 Cookie,像上图 Expires 的值为 Session,表示的就是会话性 Cookie。当为会话性 Cookie 的时候,值保存在客户端内存中,并在用户关闭浏览器时失效。需要注意的是,有些浏览器提供了会话恢复功能,这种情况下即使关闭了浏览器,会话期 Cookie 也会被保留下来,就好像浏览器从来没有关闭一样。
与会话性 Cookie 相对的是持久性 Cookie,持久性 Cookies 会保存在用户的硬盘中,直至过期或者清除 Cookie。这里值得注意的是,设定的日期和时间只与客户端相关,而不是服务端。

如果 max-Age 属性为正数时,浏览器会将其持久化,即写到对应的 Cookie 文件中。
当 max-Age 属性为负数,则表示该 Cookie 只是一个会话性 Cookie。
当 max-Age 为 0 时,则会立即删除这个 Cookie。
假如 Expires 和 Max-Age 都存在,Max-Age 优先级更高。

假如没有指定,那么默认值为当前文档访问地址中的主机部分(但是不包含子域名)。

Path 指定了一个 URL 路径,这个路径必须出现在要请求的资源的路径中才可以发送 Cookie 首部。

标记为 Secure 的 Cookie 只应通过被HTTPS协议加密过的请求发送给服务端。使用 HTTPS 安全协议,可以保护 Cookie 在浏览器和 Web 服务器间的传输过程中不被窃取和篡改。

设置 HTTPOnly 属性可以防止客户端脚本通过 document.cookie 等方式访问 Cookie,有助于避免 XSS 攻击。

SameSite 是最近非常值得一提的内容,因为 2 月份发布的 Chrome80 版本中默认屏蔽了第三方的 Cookie,这会导致阿里系的很多应用都产生问题,为此还专门成立了问题小组,推动各 BU 进行改造。
SameSite 属性可以让 Cookie 在跨站请求时不会被发送,从而可以阻止跨站请求伪造攻击(CSRF)

SameSite 可以有下面三种值:

  1. Strict 仅允许一方请求携带 Cookie,即浏览器将只发送相同站点请求的 Cookie,即当前网页 URL 与请求目标 URL 完全一致。
  2. Lax 允许部分第三方请求携带 Cookie
  3. None 无论是否跨站都会发送 Cookie
    之前默认是 None 的,Chrome80 后默认是 Lax。

解决方案就是设置 SameSite 为 none。

同源(域):两个 URL 的协议/主机名/端口一致。CORS 是根据请求头的 Origin 字段判断
同站:只要两个 URL 的 eTLD+1 相同即可,不需要考虑协议和端口。eTLD+1 则表示,有效顶级域名 + 二级域名。

  1. HTTP 接口不支持 SameSite=none
    如果你想加 SameSite=none 属性,那么该 Cookie 就必须同时加上 Secure 属性,表示只有在 HTTPS 协议下该 Cookie 才会被发送。
  2. 需要 UA 检测,部分浏览器不能加 SameSite=none
    IOS 12 的 Safari 以及老版本的一些 Chrome 会把 SameSite=none 识别成 SameSite=Strict,所以服务端必须在下发 Set-Cookie 响应头时进行 User-Agent 检测,对这些浏览器不下发 SameSite=none 属性

Cookie 主要用于以下三个方面:

  1. 会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)
  2. 个性化设置(如用户自定义设置、主题等)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
机器学习是一种人工智能(AI)的子领域,致力于研究如何利用数据和算法让计算机系统具备学习能力,从而能够自动地完成特定任务或者改进自身性能。机器学习的核心思想是让计算机系统通过学习数据中的模式和规律来实现目标,而不需要显式地编程。 机器学习应用非常广泛,包括但不限于以下领域: 图像识别和计算机视觉: 机器学习在图像识别、目标检测、人脸识别、图像分割等方面有着广泛的应用。例如,通过深度学习技术,可以训练神经网络来识别图像中的对象、人脸或者场景,用于智能监控、自动驾驶、医学影像分析等领域。 自然语言处理: 机器学习在自然语言处理领域有着重要的应用,包括文本分类、情感分析、机器翻译、语音识别等。例如,通过深度学习模型,可以训练神经网络来理解和生成自然语言,用于智能客服、智能助手、机器翻译等场景。 推荐系统: 推荐系统利用机器学习算法分析用户的行为和偏好,为用户推荐个性化的产品或服务。例如,电商网站可以利用机器学习算法分析用户的购买历史和浏览行为,向用户推荐感兴趣的商品。 预测和预测分析: 机器学习可以用于预测未来事件的发生概率或者趋势。例如,金融领域可以利用机器学习算法进行股票价格预测、信用评分、欺诈检测等。 医疗诊断和生物信息学: 机器学习在医疗诊断、药物研发、基因组学等领域有着重要的应用。例如,可以利用机器学习算法分析医学影像数据进行疾病诊断,或者利用机器学习算法分析基因数据进行疾病风险预测。 智能交通和物联网: 机器学习可以应用于智能交通系统、智能城市管理和物联网等领域。例如,可以利用机器学习算法分析交通数据优化交通流量,或者利用机器学习算法分析传感器数据监测设备状态。 以上仅是机器学习应用的一部分,随着机器学习技术的不断发展和应用场景的不断拓展,机器学习在各个领域都有着重要的应用价值,并且正在改变我们的生活和工作方式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值