浏览器+前端知识

浏览器多进程到JS单线程,JS运行机制最全面的一次梳理

浏览器内核进程——渲染引擎:负责取得网页的内容(html,xml和图像等),整理讯息(例如假如css),以及计算网页的显示方式,然后输出到显示器或打印机。浏览器的内核的不同对于网页的语法解释会有不同,所以渲染的效果也不同。所有网页浏览器、电子邮件客户端以及它需要编辑、显示网络内容的应用程序都需要内核。

JS引擎线程——JS引擎:解析和执行JavaScript来实现网页的动态效果。

http和浏览器的工作原理和内部机制要巩固一下,特别是涉及到性能、进程线程、同步异步什么的

浏览器是多进程的

1 浏览器都包含哪些进程?

  1. Browser进程:浏览器的主进程(负责协调、主控),只有一个。作用有
    • 负责浏览器界面显示,与用户交互。如前进,后退等
    • 负责各个页面的管理,创建和销毁其他进程
    • 将Renderer进程得到的内存中的Bitmap,绘制到用户界面上
    • 网络资源的管理,下载等
  2. 第三方插件进程:每种类型的插件对应一个进程,仅当使用该插件时才创建
  3. GPU进程:最多一个,用于3D绘制等
  4. 浏览器渲染进程(浏览器内核)(Renderer进程,内部是多线程的):默认每个Tab页面一个进程,互不影响。主要作用为
    • 页面渲染,脚本执行,事件处理等

重点:在浏览器中打开一个网页相当于新起了一个进程(进程内有自己的多线程)

优点:1避免单个page crash影响整个浏览器;2避免第三方插件crash影响整个浏览器;3方便使用沙盒模型隔离插件等进程,提高浏览器稳定性

2 重点:浏览器内核(渲染进程)

对于普通的前端操作来说,最终要的是渲染进程浏览器的渲染进程是多线程的

可以这样理解,页面的渲染,JS的执行,事件的循环,都在这个进程内进行。

  1. GUI渲染线程
    • 负责渲染浏览器界面,解析HTML,CSS,构建DOM树和RenderObject树,布局和绘制等。
    • 当界面需要重绘(Repaint)或由操作引发回流(reflow)时,该线程就会执行
    • 注意,GUI渲染线程与JS引擎线程是互斥的,当JS引擎执行时GUI线程会被挂起(相当于被冻结了),GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行。
  2. JS引擎线程
    • 也称为JS内核,负责处理Javascript脚本程序。(例如V8引擎)
    • JS引擎线程负责解析Javascript脚本,运行代码。
    • JS引擎一直等待着任务队列中任务的到来,然后加以处理,一个Tab页(renderer进程)中无论什么时候都只有一个JS线程在运行JS程序
    • 同样注意,GUI渲染线程与JS引擎线程是互斥的,所以如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞。
  3. 事件触发线程
    • 归属于浏览器而不是JS引擎,用来控制事件循环(可以理解,JS引擎自己都忙不过来,需要浏览器另开线程协助)
    • 当JS引擎执行代码块如setTimeOut时(也可来自浏览器内核的其他线程,如鼠标点击、AJAX异步请求等),会将对应任务添加到事件线程中
    • 当对应的事件符合触发条件被触发时,该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理
    • 注意,由于JS的单线程关系,所以这些待处理队列中的事件都得排队等待JS引擎处理(当JS引擎空闲时才会去执行)
  4. 定时触发器线程
    • 传说中的setIntervalsetTimeout所在线程
    • 浏览器定时计数器并不是由JavaScript引擎计数的,(因为JavaScript引擎是单线程的, 如果处于阻塞线程状态就会影响记计时的准确)
    • 因此通过单独线程来计时并触发定时(计时完毕后,添加到事件队列中,等待JS引擎空闲后执行)
    • 注意,W3C在HTML标准中规定,规定要求setTimeout中低于4ms的时间间隔算为4ms。
  5. 异步http请求线程
    • 在XMLHttpRequest在连接后是通过浏览器新开一个线程请求
    • 将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中。再由JavaScript引擎执行。

浏览器渲染流程

  1. 解析html建立dom树
  2. 解析css构建render树(将CSS代码解析成树形的数据结构,然后结合DOM合并成render树)
  3. 布局render树(Layout/reflow),负责各元素尺寸、位置的计算
  4. 绘制render树(paint),绘制页面像素信息
  5. 浏览器会将各层的信息发送给GPU,GPU会将各层合成(composite),显示在屏幕上。

从Event Loop谈JS的运行机制

为什么JS引擎是单线程的?1.只需要运行JS脚本;2多线程的复杂性,譬如多线程操作一般要加锁。因此最初设计时选择了单线程。

属于浏览器页面初次渲染完毕后的事情,JS引擎的一些运行机制分析。

JS引擎是单线程:1 JS引擎线程;2事件触发线程;3定时触发器线程

事件循环机制

  • JS分为同步任务和异步任务
  • 同步任务都在主线程上执行,形成一个执行栈
  • 主线程之外,事件触发线程管理着一个任务队列,只要异步任务有了运行结果,就在任务队列之中放置一个事件。
  • 一旦执行栈中的所有同步任务执行完毕(此时JS引擎空闲),系统就会读取任务队列,将可运行的异步任务添加到可执行栈中,开始执行。

image-20190420141404129

  • 主线程运行时会产生执行栈, 栈中的代码调用某些api时,它们会在事件队列中添加各种事件(当满足触发条件后,如ajax请求完毕)
  • 而栈中的代码执行完毕,就会读取事件队列中的事件,去执行那些回调
  • (如此循环;注意,总是要等待栈中的代码执行完毕后才会去读取事件队列中的事件)

定时器

调用setTimeout后,是如何等待特定时间后才添加到事件队列中的?

是由定时器线程控制(因为JS引擎自己都忙不过来,根本无暇分身)

为什么要单独的定时器线程?因为JavaScript引擎是单线程的, 如果处于阻塞线程状态就会影响记计时的准确,因此很有必要单独开一个线程用来计时。

什么时候会用到定时器线程?当使用setTimeout或setInterval时,它需要定时器线程计时,计时完成后就会将特定的事件推入事件队列中。

前端工程

webpack

作用:webpack会将不同类型的静态资源,打包成一个JS,在HTML引用该JS的时候,其可以正常运行。

好处:希望零碎的JS打包在一起,减少HTTP请求;使用模块依赖,更新某一模块的时候只需要改一次即可。

开发APP的时候,是一整个JS加载到浏览器中来渲染。可以以该JS文件作为入口。

entry:入口为src/index.js;出口为文件名bundle.js和路径;module的rules

webpack会将不同类型的静态资源(index.js文件及其所依赖的Vue、App等),打包成一个JS(完整的bundle.js),在HTML引用该JS的时候,其可以正常运行(且打包出来的是可以在浏览器中直接运行的JS代码)。

XSS

XSS 全称 Cross Site Scripting ,跨站脚本攻击。

转义:是让用户的输入不要变成程序,输入的什么就让它输出成什么。

CSP:内容安全策略,Content Security Policy:定义页面上哪一些内容是可被信任的,哪一些内容是不被信任的。比较灵活。

CSRF

CSRF: Cross Site Request Foggy,即跨站请求攻击。从别的网站发起一个请求到我们的网站的。

当一个用户登录我们的网站后,在 Cookies 中会存放用户的身份凭证。在大部分时候,就是一个 SessionId 。当用户下次访问我们的网站的时候,我们用这个凭证识别出用户是谁,有没有登录态。

攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账……造成的问题包括:个人隐私泄露以及财产安全。

POST\GET请求:如果这个地址是一个发表文章、发布微博甚至转账之类的链接,那用户就在不知情的情况下进行了一些操作。这也是比较严重的安全问题。

判断来源:比较简单,主要是判断referer这个头,如果不是自己的网站,就返回错误。

加 token :即同样的随机 token,在 cookies 中放一份,在表单中再放一份。这样第三方网站就无法获取到这个 token 是什么。

验证码:每次的用户提交都需要用户在表单中填写一个图片上的随机字符串,

项目上线

npm run build

前端的目的

搭建前端工程

网络优化

API定制

nodejs层

html14.一个页面上有大量的图片(大型电商网站),加载很慢,你有哪些方法优化这些图片的加载,给用户更好的体验。

  • 图片懒加载,在页面上的未可视区域可以添加一个滚动条事件,判断图片位置与浏览器顶端的距离与页面的距离,如果前者小于后者,优先加载。
  • 如果为幻灯片、相册等,可以使用图片预加载技术,将当前展示图片的前一张和后一张优先下载。
  • 如果图片为css图片,可以使用CSSsprite,SVGsprite,Iconfont、Base64等技术。
  • 如果图片过大,可以使用特殊编码的图片,加载时会先加载一张压缩的特别厉害的缩略图,以提高用户体验。
  • 如果图片展示区域小于图片的真实大小,则因在服务器端根据业务需要先行进行图片压缩,图片压缩后大小与展示一致。

JS12.(设计题)想实现一个对页面某个节点的拖曳?如何做?(使用原生JS)

回答出概念即可,下面是几个要点

  • 给需要拖拽的节点绑定mousedown, mousemove, mouseup事件
  • mousedown事件触发后,开始拖拽
  • mousemove时,需要通过event.clientX和clientY获取拖拽位置,并实时更新位置
  • mouseup时,拖拽结束
  • 需要注意浏览器边界的情况