(一)浏览器架构
1.演进
- 单进程架构:早期的浏览器架构
- 多进程架构:现代浏览器主流的架构,把每个进程(主进程等)隔离起来,运行在独立的沙箱里,安全性较高
- 面向服务架构:2的升级版,运行之前需要定义接口,通过调用接口
- 对比:
2.任务管理器
打开谷歌的工具可以看到它的各个进程
3.多进程分工
- 主进程:主要负责页面展示逻辑,用户交互,子进程管理
- GPU进程:负责UI绘制,包含整个浏览器的UI
- 网络进程:加载网络资源
- 标签页(渲染进程):控制tab中的所有内容,将html,css和javascript转化Wie用户可交互的网页
- 插件进程:控制网站运行的插件
- 其他进程:
4.思考
早期的硬件比较昂贵,硬件发展不足,所以存在单进程 面向服务架构未来会替代多进程,他会根据用户的硬件来适配,当硬件不足时,会降低为多进程架构。
(二)渲染进程
1.常见浏览器内核
2.多进程架构
内部是多线程实现,负责页面渲染,脚本执行,事件处理,网络请求等。
3.JS引擎VS渲染引擎
- 解析执行JS
- XML解析生成渲染树,显示在屏幕中
- 桥接方式通信
4.多线程工作流程
- 网络线程负责加载网页资源
- JS引擎解析JS脚本并且执行
- 在JS解析引擎空闲时,渲染线程会立刻工作
- 在用户交互、定时器操作等产生回调函数放入任务对列中
- 事件线程进行事件循环,将队列中的任务取出交给JS引擎执行
5.笔试题
const now = Date.now()
setTimeout(() => {
console.log('time10',Date.now()-now)
}, 10)
setTimeout(() => {
console.log('time30',Date.now()-now)
}, 30)
while (true) {
if (Date.now() - now >= 20) {
break
}
}
console.log(Date.now()-now)
先输出最后一行的时间,20,接着接口回调到第一个setTimeout ,输出20,第二个输出30,但是实际偏差会在4秒以内。
(三)chrome浏览器的原理
1.如何展示网页
- 浏览器地址栏在输入url之后发生什么
2.输入处理
- 浏览器的UI线程会先检测用户输入的是URL地址,还是一个query查询
- 如果是URL地址,则会直接请求站点资源
- 如果是query,则会将输入发送给搜索引擎
3.开始导航
- 按下回车之后,UI线程通知网络线程发起一个网络请求,获取站点内容
- 在请求过程中,tab处于loading状态中
4.读取响应
- 在接收到http响应后,先检查响应头的媒体类型
- 如果响应的主体是一个HTML文件,浏览器将内容交给渲染进程处理
- 如果拿到的是其他类型的文件,比如ZIP,exe等,则交给下载管理器处理
5寻找渲染进程
- 网络线程做完所有检查后,会告知主进程数据已准备完毕,主进程确认后为这个站点寻找一个渲染进程
- 主进程通过IPC消息告知渲染进程去处理本次导航
- 之后渲染进程接受数据并告知自己开始处理了,导航结束,进入文档的加载阶段
6资源加载
- 在收到主进程的消息后。开始加载HTML文档
- 除此之外,还需要加载子资源,比如图片或者css样式文件
7构建渲染树
- 构建DOM树,将HTML文本转化为浏览器能够理解的结构
- 构建CSSOM树,将css代码转化为浏览器可以理解的CSSOM
- 构建渲染树,渲染树是DOM树和CSSOM树的结合
8页面布局
- 根据渲染树计算每个节点的位置和大小
- 在浏览页面区域绘制元素边框
- 遍历渲染树,将元素以盒模型写入文档流
9页面绘制
- 构建图层:为特定的节点生成专用的图层
- 绘制图层:一个图层分为多个绘制指令,然后将指令按顺序组成一个绘制列表,交给合成线程
- 合成线程接受指令生成图块
- 栅格线程将图块进行栅格化
- 展示在屏幕上
首屏优化
- 压缩、分包、删除无用的代码
- 静态资源分离
- JS脚本非阻塞加载
- 缓存策略
- SSR :
-
更快的首屏加载:这一点在慢网速或者运行缓慢的设备上尤为重要。服务端渲染的 HTML 无需等到所有的 JavaScript 都下载并执行完成之后才显示,所以你的用户将会更快地看到完整渲染的页面。除此之外,数据获取过程在首次访问时在服务端完成,相比于从客户端获取,可能有更快的数据库连接。这通常可以带来更高的核心 Web 指标评分、更好的用户体验,而对于那些“首屏加载速度与转化率直接相关”的应用来说,这点可能至关重要。
-
统一的心智模型:你可以使用相同的语言以及相同的声明式、面向组件的心智模型来开发整个应用,而不需要在后端模板系统和前端框架之间来回切换。
-
更好的 SEO:搜索引擎爬虫可以直接看到完全渲染的页面。
- 预置loading,骨架屏
渲染优化
- GPU加速
- 减少回流,重构
- 离屏渲染
- 懒加载 懒加载,即延迟加载(Lazyload)。简单来说就是一个长页面中需要展示很多图像的时候,如果在进入页面的时候一次性把所有图片加载完,需要很长的时间。为了提升用户体验,我们使用懒加载,当图片出现在浏览器可视区域时,才加载图片。例如各种电商页面。
- 加快页面打开速度,提升用户体验
- 减少服务器压力和浏览器的负担
js优化
- 防止内存泄漏: 产生内存泄漏:使用全局变量会有内存泄漏的风险;有一些dom,dom删除了,但是js变量没清空,dom引用会一直存在;定时器,忘记清楚会导致内存泄漏,可以封装一种可以自动清除的定时器
- 尽快结束循环:满足条件后尽快结束
- 合理使用闭包:减少单列元素的创建
- 减少Dom的访问
- 防抖,节流:防止多次提交,最后只会提交我们最后一次结果;保证在规定时间之内多次调用,只会调用一次结果。
- web workers:和js引擎相互独立,可以用在图片,音频等方面的处理
(三)跨端容器
1为什么需要
- 减少开发成本,效率
- 一致性体验
- 前段开发生态
2跨端方案
1.WebView
- 即网页视图,用于加载网页URL,展示其内容的控件
- 可以内嵌在移动端APP内,实现前段混合开发,大多数都是基于WebView的二次开发,
WebView 分类
WebView 的优势
- 一次开发,学习成本低
- 随时发布,即时更新
- 移动设备性能不断提升,性能有保障
- 通过JSBridge和原生系统交互,实现负责功能
WebView 使用原生能力
- JavaScript调用Native
- API注入:Native获取JS环境的上下文,对挂载的对象或者方法进行拦截
- 使用
WebView URL Scheme跳转拦截 - IOS 上 使用此方法
window.webkit.messageHandler可以直接通信
- Native调用JS
- 一般直接通过webview 暴露的API执行JS代码,每个APP都会自己约定好自己的通信格式
- IOS
WebView.stringByEvaluatingJavaScriptFromString - Android
WebView.evaluateJavascript