二本获得阿里实习 offer 经历-宝藏篇(下)

1,058 阅读52分钟

(因字数限制分为上下文,承接上文 二本获得阿里实习 offer 经历-宝藏篇(上)

系列如下:觉得有用要点赞!✨


浏览器

image.png

进程

状态

运行态(该时刻进程实际占用CPU)。
就绪态(可运行,但因为其他进程正在运行而暂时停止)。
阻塞态(除非某种外部事件发生,否则进程不能运行)。

通信

  • 匿名管道

    顾名思义,它没有名字标识,匿名管道是特殊文件只存在于内存,没有存在于文件系统中,shell 命令中的【 | 】竖线就是匿名管道,通信的数据是无格式的流并且大小受限,通信的方式是单向的,数据只能在一个方向上流动,如果要双向通信,需要创建两个管道,再来匿名管道是只能用于存在父子关系的进程间通信,匿名管道的生命周期随着进程创建而建立,随着进程终止而消失。
    
  • 命名管道

    突破了匿名管道只能在亲缘关系进程间的通信限制,因为使用命名管道的前提,需要在文件系统创建一个类型为 p 的设备文件,那么毫无关系的进程就可以通过这个设备文件进行通信。另外,不管是匿名管道还是命名管道,进程写入的数据都是缓存在内核中,另一个进程读取数据时候自然也是从内核中获取,同时通信数据都遵循先进先出原则,不支持 lseek 之类的文件定位操作。
    
  • 消息队列

    克服了管道通信的数据是无格式的字节流的问题,消息队列实际上是保存在内核的「消息链表」,消息队列的消息体是可以用户自定义的数据类型,发送数据时,会被分成一个一个独立的消息体,当然接收数据时,也要与发送方发送的消息体的数据类型保持一致,这样才能保证读取的数据是正确的。消息队列通信的速度不是最及时的,毕竟每次数据的写入和读取都需要经过用户态与内核态之间的拷贝过程。
    
  • 共享内存

    可以解决消息队列通信中用户态与内核态之间数据拷贝过程带来的开销,它直接分配一个共享空间,每个进程都可以直接访问,就像访问进程自己的空间一样快捷方便,不需要陷入内核态或者系统调用,大大提高了通信的速度,享有最快的进程间通信方式之名。但是便捷高效的共享内存通信,带来新的问题,多进程竞争同个共享资源会造成数据的错乱。
    
  • 信号量

    那么,就需要信号量来保护共享资源,以确保任何时刻只能有一个进程访问共享资源,这种方式就是互斥访问。信号量不仅可以实现访问的互斥性,还可以实现进程间的同步,信号量其实是一个计数器,表示的是资源个数,其值可以通过两个原子操作来控制,分别是 P 操作和 V 操作。
    
  • 信号

    与信号量名字很相似的叫信号,它俩名字虽然相似,但功能一点儿都不一样。信号是进程间通信机制中唯一的异步通信机制,信号可以在应用进程和内核之间直接交互,内核也可以利用信号来通知用户空间的进程发生了哪些系统事件,信号事件的来源主要有硬件来源(如键盘 Cltr+C )和软件来源(如 kill 命令),一旦有信号发生,进程有三种方式响应信号 1. 执行默认操作、2. 捕捉信号、3. 忽略信号。有两个信号是应用进程无法捕捉和忽略的,即 SIGKILL 和 SEGSTOP,这是为了方便我们能在任何时候结束或停止某个进程。
    
  • Socket 通信

    前面说到的通信机制,都是工作于同一台主机,如果要与不同主机的进程间通信,那么就需要 Socket 通信了。Socket 实际上不仅用于不同的主机进程间通信,还可以用于本地主机进程间通信,可根据创建 Socket 的类型不同,分为三种常见的通信方式,一个是基于 TCP 协议的通信方式,一个是基于 UDP 协议的通信方式,一个是本地进程间通信方式。
    

线程

使用原因

1. 在许多应用中同时发生着多种活动。其中某些活动随着时间的推移会被阻塞。通过将这些应用程序分解成可以准并行运行的多个顺序线程,程序设计模型会变得更简单。
2. 由于线程比进程更轻量级,所以它们比进程更容易(即更快)创建,也更容易撤销。在许多系统中,创建一个线程较创建一个进程要快10~100倍。
3. 若多个线程都是 CPU 密集型的,那么并不能获得性能上的增强,但是如果存在着大量的计算和大量的 I/O 处理,拥有多个线程允许这些活动彼此重叠进行,从而会加快应用程序执行的速度。

通信

同个进程下的线程之间都是共享进程的资源,只要是共享变量都可以做到线程间通信,比如全局变量,所以对于线程间关注的不是通信方式,而是关注多线程竞争共享资源的问题,信号量也同样可以在线程间实现互斥与同步

juejin.cn/post/686993…

  • 互斥

    可保证任意时刻只有一个线程访问共享资源;
    
  • 同步

    可保证线程 A 应在线程 B 之前执行;
    

事件引擎

渲染引擎

事件循环

JS 引擎

  • async 和 defer 及区别

浏览器内核

理解

主要分成两部分:渲染引擎和 JS 引擎。

- 渲染引擎的职责就是渲染,即在浏览器窗口中显示所请求的内容。默认情况下,渲染引擎可以显示 html、xml 文档及图片,它也可以借助插件(一种浏览器扩展)显示其他类型数据,例如使用 PDF 阅读器插件,可以显示 PDF 格式。

- JS 引擎:解析和执行 javascript 来实现网页的动态效果。

最开始渲染引擎和 JS 引擎并没有区分的很明确,后来 JS 引擎越来越独立,内核就倾向于只指渲染引擎。

常见内核及比较

- Trident:这种浏览器内核是 IE 浏览器用的内核,因为在早期IE 占有大量的市场份额,所以这种内核比较流行,以前有很多网页也是根据这个内核的标准来编写的,但是实际上这个内核对真正的网页标准支持不是很好。但是由于 IE 的高市场占有率,微软也很长时间没有更新 Trident 内核,就导致了 Trident 内核和 W3C 标准脱节。还有就是 Trident 内核的大量 Bug 等安全问题没有得到解决,加上一些专家学者公开自己认为 IE 浏览器不安全的观点,使很多用户开始转向其他浏览器。
- Gecko:这是 Firefox 和 Flock 所采用的内核,这个内核的优点就是功能强大、丰富,可以支持很多复杂网页效果和浏览器扩展接口,但是代价是也显而易见就是要消耗很多的资源,比如内存。
- Presto:Opera 曾经采用的就是 Presto 内核,Presto 内核被称为公认的浏览网页速度最快的内核,这得益于它在开发时的天生优势,在处理 JS 脚本等脚本语言时,会比其他的内核快3倍左右,缺点就是为了达到很快的速度而丢掉了一部分网页兼容性。
- Webkit:Webkit 是 Safari 采用的内核,它的优点就是网页浏览速度较快,虽然不及 Presto 但是也胜于 Gecko 和 Trident,缺点是对于网页代码的容错性不高,也就是说对网页代码的兼容性较低,会使一些编写不标准的网页无法正确显示。WebKit 前身是 KDE 小组的 KHTML 引擎,可以说 WebKit 是 KHTML 的一个开源的分支。
- Blink:谷歌在 Chromium Blog 上发表博客,称将与苹果的开源浏览器核心 Webkit 分道扬镳,在 Chromium 项目中研发 Blink 渲染引擎(即浏览器核心),内置于 Chrome 浏览器之中。其实 Blink 引擎就是 Webkit 的一个分支,就像 webkit 是 KHTML 的分支一样。Blink 引擎现在是谷歌公司与 Opera Software 共同研发,上面提到过的,Opera 弃用了自己的 Presto 内核,加入 Google 阵营,跟随谷歌一起研发 Blink。

requestAnimationFrame

与setTimeout区别

按帧对网页进行重绘

浏览器架构

* 用户界面
  * 主进程
  * 内核
      * 渲染引擎
      * JS 引擎
          * 执行栈
      * 事件触发线程
          * 消息队列
              * 微任务
              * 宏任务
      * 网络异步线程
      * 定时器线程

跨域

为什么存在

  • 浏览器开放,安全需限制

  • 同源策略

    - Ajax同源策略
    - DOM同源策略
    

解决方式

  • JSONP

  • Cros

    - 服务器配置
      - Access-Control-Allow-(Origin/Methods/Headers/Credentials/Max-Age)
    
    - 简单请求
    - 非简单请求
    - 预请求
    
  • iframe

缓存

强/协商缓存

- 各个常见的值
- 优缺点
- ETag的构成

存储技术

cookie

localStorage

sessionStorage

indexDB

渲染页面

输入URL到页面的呈现

不良现象

  • FOUC(样式闪烁)

    主要指的是样式闪烁的问题,由于浏览器渲染机制(比如firefox),在 CSS 加载之前,先呈现了 HTML,就会导致展示出无样式内容,然后样式突然呈现的现象。会出现这个问题的原因主要是 css 加载时间过长,或者 css 被放在了文档底部。
    
  • 白屏

重绘和回流

  • 减少回流

    1)使用 transform 替代 top2)不要把节点的属性值放在一个循环里当成循环里的变量
    (3)不要使用 table 布局,可能很小的一个小改动会造成整个 table 的重新布局
    (4)把 DOM 离线后修改。如:使用 documentFragment 对象在内存里操作 DOM
    (5)不要一条一条地修改 DOM 的样式。与其这样,还不如预先定义好 css 的 class,然后修改 DOM 的 className。
    

image.png

网络

image.png

【计算机网络】-林大人的小屋

七层/五层IOS模型

Ajax

手写

状态码

统一资源

URI

URI: Uniform Resource Identifier 指的是统一资源标识符

URL

URL: Uniform Resource Location 指的是统一资源定位符

URN

URN: Universal Resource Name 指的是统一资源名称

Post 和 Get 的区别

Post 和 Get 是 HTTP 请求的两种方法。

1)从应用场景上来说,GET 请求是一个幂等的请求,一般 Get 请求用于对服务器资源不会产生影响的场景,比如说请求一个网页。而 Post 不是一个幂等的请求,一般用于对服务器资源会产生影响的情景。比如注册用户这一类的操作。

(2)因为不同的应用场景,所以浏览器一般会对 Get 请求缓存,但很少对 Post 请求缓存。

(3)从发送的报文格式来说,Get 请求的报文中实体部分为空,Post 请求的报文中实体部分一般为向服务器发送的数据。

(4)但是 Get 请求也可以将请求的参数放入 url 中向服务器发送,这样的做法相对于 Post 请求来说,一个方面是不太安全,因为请求的 url 会被保留在历史记录中。并且浏览器由于对 url 有一个长度上的限制,所以会影响 get 请求发送数据时的长度。这个限制是浏览器规定的,并不是 RFC 规定的。还有就是 post 的参数传递支持更多的数据类型。

浏览器输入 url 地址回车后的行为

(1)首先会对 URL 进行解析,分析所需要使用的传输协议和请求的资源的路径。如果输入的 URL 中的协议或者主机名不合法,将会把地址栏中输入的内容传递给搜索引擎。如果没有问题,浏览器会检查 URL 中是否出现了非法字符,如果存在非法字符,则对非法字符进行转义后再进行下一过程。

(2)浏览器会判断所请求的资源是否在缓存里,如果请求的资源在缓存里并且没有失效,那么就直接使用,否则向 DNS 服务器发起新的请求。

(3)下一步我们首先需要获取的是输入的 URL 中的域名的 IP 地址,首先会判断本地是否有该域名的 IP 地址的缓存,如果有则使用,如果没有则向本地 DNS 服务器发起请求。
    - 本地 DNS 服务器也会先检查是否存在缓存,如果没有就会先向根域名服务器发起请求,获得负责的顶级域名服务器的地址后。
    - 再向顶级域名服务器请求,然后获得负责的权威域名服务器的地址后。
    - 再向权威域名服务器发起请求,最终获得域名的 IP 地址后,本地 DNS 服务器再将这个 IP 地址返回给请求的用户。
    用户向本地 DNS 服务器发起请求属于递归请求,本地 DNS 服务器向各级域名服务器发起请求属于迭代请求。

(4)当浏览器得到 IP 地址后,数据传输还需要知道目的主机 MAC 地址,因为应用层下发数据给传输层,TCP 协议会指定源端口号和目的端口号,然后下发给网络层。
    - 网络层会将本机地址作为源地址,获取的 IP 地址作为目的地址。
    - 然后将下发给数据链路层,数据链路层的发送需要加入通信双方的 MAC 地址,我们本机的 MAC 地址作为源 MAC 地址,目的 MAC 地址需要分情况处理,通过将 IP 地址与我们本机的子网掩码相与,我们可以判断我们是否与请求主机在同一个子网里。
    - 如果在同一个子网里,我们可以使用 APR 协议获取到目的主机的 MAC 地址。
    - 如果我们不在一个子网里,那么我们的请求应该转发给我们的网关,由它代为转发,此时同样可以通过 ARP 协议来获取网关的 MAC 地址,此时目的主机的 MAC 地址应该为网关的地址。

(5)下面是 TCP 建立连接的三次握手

(6)如果使用的是 HTTPS 协议,在通信前还存在 TLS 的一个四次握手的过程。

(7)当页面请求发送到服务器端后,服务器端会返回一个 html 文件作为响应,浏览器接收到响应后,开始对 html 文件进行解析,开始页面的渲染过程。

(8)浏览器首先会根据 html 文件构建 DOM 树,根据解析到的 css 文件构建 CSSOM 树,如果遇到 script 标签,则判断是否含有 defer 或者 async 属性,要不然 script 的加载和执行会造成页面的渲染的阻塞。当 DOM 树和 CSSOM 树建立好后,根据它们来构建渲染树。
    渲染树构建好后,会根据渲染树来进行布局。布局完成后,最后使用浏览器的 UI 接口对页面进行绘制。这个时候整个页面就显示出来了。

(9)最后一步是 TCP 断开连接的四次挥手过程。

CDN

CDN 是一个内容分发网络,通过对源网站资源的缓存,利用本身多台位于不同地域、不同运营商的服务器,向用户提供资就近访问的功能。也就是说,用户的请求并不是直接发送给源网站,而是发送给CDN 服务器,由 CND 服务器将请求定位到最近的含有该资源的服务器上去请求。这样有利于提高网站的访问速度,同时通过这种方式也减轻了源服务器的访问压力。

优势

1. 为了加速网站的访问(物理地域上的优势)
2. 为了实现跨运营商、跨地域的全网覆盖
3. 为了保障你的网站安全
   - CDN的负载均衡和分布式存储技术,可以加强网站的可靠性,相当无无形中给你的网站添加了一把保护伞,应对绝大部分的互联网攻击事件。防攻击系统也能避免网站遭到恶意攻击。
4. 为了异地备援
   - 当某个服务器发生意外故障时,系统将会调用其他临近的健康服务器节点进行服务,进而提供接近100%的可靠性,这就让你的网站可以做到永不宕机。
5. 为了节约成本投入

代理

正向代理

常说的代理也就是指正向代理,正向代理的过程,它隐藏了真实的请求客户端。
服务端不知道真实的客户端是谁,客户端请求的服务都被代理服务器代替来请求。

反向代理

反向代理隐藏了真实的服务端。
当我们请求一个网站的时候,背后可能有成千上万台服务器为我们服务,但具体是哪一台,我们不知道,也不需要知道,我们只需要知道反向代理服务器是谁就好了,反向代理服务器会帮我们把请求转发到真实的服务器那里去。反向代理器一般用来实现负载平衡!

负载均衡

也是一个面试考点喔

即时通讯

基于 http 协议

  • 短轮询

    - 短轮询的基本思路就是浏览器每隔一段时间向浏览器发送 http 请求,服务器端在收到请求后,不论是否有数据更新,都直接进行响应。
    - 这种方式实现的即时通信,本质上还是浏览器发送请求,服务器接受请求的一个过程,通过让客户端不断的进行请求,使得客户端能够模拟实时地收到服务器端的数据的变化。这种方式的优点是比较简单,易于理解。
    - 缺点是这种方式由于需要不断的建立 http 连接,严重浪费了服务器端和客户端的资源。当用户增加时,服务器端的压力就会变大,这是很不合理的。
    
  • 长轮询

    - 长轮询的基本思路是,首先由客户端向服务器发起请求,当服务器收到客户端发来的请求后,服务器端不会直接进行响应,而是先将这个请求挂起,然后判断服务器端数据是否有更新。
    - 如果有更新,则进行响应,如果一直没有数据,则到达一定的时间限制才返回。客户端 JavaScript 响应处理函数会在处理完服务器返回的信息后,再次发出请求,重新建立连接。
    - 长轮询和短轮询比起来,它的优点是明显减少了很多不必要的 http 请求次数,相比之下节约了资源。长轮询的缺点在于,连接挂起也会导致资源的浪费。
    
  • SSE

    - SSE 的基本思想是,服务器使用流信息向服务器推送信息。
    - 严格地说,http 协议无法做到服务器主动推送信息。但是,有一种变通方法,就是服务器向客户端声明,接下来要发送的是流信息。也就是说,发送的不是一次性的数据包,而是一个数据流,会连续不断地发送过来。这时,客户端不会关闭连接,会一直等着服务器发过来的新的数据流,视频播放就是这样的例子。
    - SSE 就是利用这种机制,使用流信息向浏览器推送信息。它基于 http 协议,目前除了 IE/Edge,其他浏览器都支持。它相对于前面两种方式来说,不需要建立过多的 http 请求,相比之下节约了资源。
    

WebSocket

- WebSocket 是 Html5 定义的一个新协议,与传统的 http 协议不同,该协议允许由服务器主动的向客户端推送信息。
- WebSocket 是一个全双工的协议,也就是通信双方是平等的,可以相互发送消息,而 SSE 的方式是单向通信的,只能由服务器端向客户端推送信息,如果客户端需要发送信息就是属于下一个 http 请求了。
- 使用 WebSocket 协议的缺点是在服务器端的配置比较复杂。

网络安全

【Web安全/操作系统/性能优化】-大大的小屋

XSS

  • 预防

  • 类型

    - 存储型
    - 反射型
    - DOM型
    

Csrf

  • token

    - 存储方式
      - localStorage
      - cookie
        - 自动发送,不能跨域
      - HTTP的Authorization属性
    
  • cookie

传输层

传输层协议主要是为不同主机上的不同进程间提供了逻辑通信的功能。传输层只工作在端系统中。

UDP

UDP 是一种无连接的,不可靠的传输层协议。它只提供了传输层需要实现的最低限度的功能,除了复用/分解功能和少量的差错检测外,它几乎没有对 IP 增加其他的东西。UDP 协议适用于对实时性要求高的应用场景。
  • 特点

    - 使用 UDP 时,在发送报文段之前,通信双方没有握手的过程,因此 UDP 被称为是无连接的传输层协议。因为没有握手过程,相对于 TCP 来说,没有建立连接的时延。因为没有连接,所以不需要在端系统中保存连接的状态。
    - UDP 提供尽力而为的交付服务,也就是说 UDP 协议不保证数据的可靠交付。
    - UDP 没有拥塞控制和流量控制的机制,所以 UDP 报文段的发送速率没有限制。
    - 因为一个 UDP 套接字只使用目的地址和目的端口来标识,所以 UDP 可以支持一对一、一对多、多对一和多对多的交互通信。
    - UDP 首部小,只有 8 个字节。
    
  • 报文段结构

    - UDP 报文段由首部和应用数据组成。
    - 报文段首部包含四个字段,分别是源端口号、目的端口号、长度和检验和,每个字段的长度为两个字节。
    - 长度字段指的是整个报文段的长度,包含了首部和应用数据的大小。
    - 校验和是 UDP 提供的一种差错校验机制。虽然提供了差错校验的机制,但是 UDP 对于差错的恢复无能为力。
    

TCP

  • 特点

    - TCP 协议是面向连接的,在通信双方进行通信前,需要通过三次握手建立连接。它需要在端系统中维护双方连接的状态信息。
    - TCP 协议通过序号、确认号、定时重传、检验和等机制,来提供可靠的数据传输服务。
    - TCP 协议提供的是点对点的服务,即它是在单个发送方和单个接收方之间的连接。
    - TCP 协议提供的是全双工的服务,也就是说连接的双方的能够向对方发送和接收数据。
    - TCP 提供了拥塞控制机制,在网络拥塞的时候会控制发送数据的速率,有助于减少数据包的丢失和减轻网络中的拥塞程度。
    - TCP 提供了流量控制机制,保证了通信双方的发送和接收速率相同。如果接收方可接收的缓存很小时,发送方会降低发送速率,避免因为缓存填满而造成的数据包的丢失。
    
  • 报文段结构

  • TCP 报文段由首部和数据组成,它的首部一般为 20 个字节。

  • 首部:源端口、目的端口、确认号、接收窗口、长度字段、标志字段、校验和

    1. 源端口和目的端口号用于报文段的多路复用和分解。
    2. 32 比特的序号和 32 比特的确认号,用与实现可靠数据运输服务。
    3. 16 比特的接收窗口字段用于实现流量控制,该字段表示接收方愿意接收的字节的数量。
    4. 4 比特的首部长度字段,该字段指示了以 32 比特的字为单位的 TCP 首部的长度。
    5. 6 比特的标志字段,ACK 字段用于指示确认序号的值是有效的,RST、SYN 和 FIN 比特用于连接建立和拆除。设置 PSH 字段指示接收方应该立即将数据交给上层,URG 字段用来指示报文段里存在紧急的数据。
    6. 校验和提供了对数据的差错检测。
    
  • 三次握手

    信号量:
    ACK:应答标志 - 当ACK = 1时,确认号字段有效,当ACK = 0时,确认号无效。
    ack:应答,值为告诉对方下一次所发数据地址 
    SYN:同步标志 - 在连接建立时用来同步序号。当SYN=1而ACK=0时,表明这是一个连接请求报文段。对方若同意建立连接,则将ACK置为1就表示这是一个接受连接的报文。
    seq:值为所发数据地址(有很多文章说是随机数,应该是数据的地址。)
    
    第一次握手:客户机主动唤醒服务器,发送:SYN=1,seq=x表示请求同步,所发数据地址为x 
        SYN(请求请求),seq(告诉服务器 - 客户端数据的地址 x)
    第二次握手:当服务器接收到数据后,返回:SYN=1,ACK=1,seq=y,ack=x+1(合并的步骤)
        ACK(应答了,ack 应答值为客户端数据地址 x(seq) + 1,确保是应答的人和发送成功),seq(告诉客户端 - 服务器的数据地址 y)
    第三次握手:客户机进行应答:ACK=1,seq=x+1,ack=y+1,表示接受到所发消息,本次数据地址为x+1,提醒服务器下次应发y+1地址的数据
        ACK(也应答了,ack 应答值为服务器的数据地址 y(seq) + 1),seq(客户端的数据地址 - 下一次要传这里了 x+1)
    
    综上:三个握手主要信号量为
    1. ACK(应答标志 1、0) - 2. ack(应答值 - 下次要发来这个地方)
    2. SYN(同步标志 1、0)- 4. seq(发送数据的地址)
    
  • 四次挥手

    信号量:
    ACK:应答标志,1为有效
    FIN:结束请求标志,1为有效(和SYN区分区分!)
    ack:应答值(也就是告知对方下一次发这里来)
    seq:所发数据地址
    
    第一次挥手:
        客户机是主动发起断开连接请求,向服务器发送:FIN=1,seq=x。
        FIN(结束请求标志有效),seq(本次所发数据地址:x)
    
    第二次挥手:
        服务器接收到数据后,向客户端发送:ACK=1,seq=y,ack=x+1。
        ACK(应答标志有效),seq(当前服务器值的地址),ack(应答值为客户端地址 x+1)
        注意这里没有返回 FIN 结束请求标志有效!
    第三次挥手:
        客户端等待,服务器数据传输完成后,再次回复FIN=1,ACK=1,seq=z,ack=x+1表示可以断开了,注意这时seq变为z(就是不同于上面)因为中间数据传输了,地址变化了。 
        FIN(结束请求标志有效),ACK(应答标志有效),seq(当前服务器值的新地址(因为是其他数据所以会变换!)),ack(应答值为客户端地址 x+1)
    第四次挥手:
        客户机最后确认关闭连接回复:ACK=1,seq=x+1,ack=z+1 
        ACK(应答标志有效),seq(当前客户端的地址 x+1 ),ack(应答值为服务器地址 y+1)
        【这里没有 FIN 是因为不用请求关闭了,前面第一次挥手请求过了】
        
    客户机最后回复后等待了2MSL「两个包数据文件的最长生命周期」。
    因为超时重发的优化算法,且来回时间各占一个生命周期,所以当包数据文件在来回过程时间内,没接受到服务器的错误反馈,则认为数据成功接收,否则重发,确保连接的可靠性。
    
  • 保证可靠性

    • 序号

    • 确认号

    • 校验和

    • ARQ 协议

      ARQ 协议指的是自动重传请求,它通过超时和重传来保证数据的可靠交付,它是 TCP 协议实现可靠数据传输的一个很重要的机制。
      
      • 停止等待 ARQ 协议

        - 停止等待 ARQ 协议的基本原理是,对于发送方来说发送方每发送一个分组,就为这个分组设置一个定时器。当发送分组的确认回答返回了,则清除定时器,发送下一个分组。如果在规定的时间内没有收到已发送分组的肯定回答,则重新发送上一个分组。
        - 对于接受方来说,每次接受到一个分组,就返回对这个分组的肯定应答,当收到冗余的分组时,就直接丢弃,并返回一个对冗余分组的确认。当收到分组损坏的情况的时候,直接丢弃。
        - 使用停止等待 ARQ 协议的缺点是每次发送分组必须等到分组确认后才能发送下一个分组,这样会造成信道的利用率过低。
        
      • 连续 ARQ 协议

        - 连续 ARQ 协议是为了解决停止等待 ARQ 协议对于信道的利用率过低的问题。它通过连续发送一组分组,然后再等待对分组的确认回答,对于如何处理分组中可能出现的差错恢复情况,一般可以使用滑动窗口协议和选择重传协议来实现。
        - 滑动窗口协议
           - 发送方维持了一个发送窗口,发送窗口以前的分组是已经发送并确认了的分组,发送窗口中包含了已经发送但未确认的分组和允许发送但还未发送的分组,发送窗口以后的分组是缓存中还不允许发送的分组。
                当发送方向接收方发送分组时,会依次发送窗口内的所有分组,并且设置一个定时器,这个定时器可以理解为是最早发送但未收到确认的分组。
                如果在定时器的时间内收到某一个分组的确认回答,则滑动窗口,将窗口的首部移动到确认分组的后一个位置,此时如果还有已发送但没有确认的分组,则重新设置定时器,如果没有了则关闭定时器。如果定时器超时,则重新发送所有已经发送但还未收到确认的分组。
          - 接收方使用的是累计确认的机制,对于所有按序到达的分组,接收方返回一个分组的肯定回答。
                如果收到了一个乱序的分组,那么接方会直接丢弃,并返回一个最近的按序到达的分组的肯定回答。使用累计确认保证了确认号以前的分组都已经按序到达了,所以发送窗口可以移动到已确认分组的后面。
          - 滑动窗口协议的缺点是因为使用了累计确认的机制,如果出现了只是窗口中的第一个分组丢失,而后面的分组都按序到达的情况的话,那么滑动窗口协议会重新发送所有的分组,这样就造成了大量不必要分组的丢弃和重传。
        
        - 选择重传协议:因为滑动窗口使用累计确认的方式,所以会造成很多不必要分组的重传。使用选择重传协议可以解决这个问题。
            - 选择重传协议在发送方维护了一个发送窗口。发送窗口的以前是已经发送并确认的分组,窗口内包含了已发送但未被确认的分组,已确认的乱序分组,和允许发送但还未发送的分组,发送窗口以后的是缓存中还不允许发送的分组。
            - 选择重传协议与滑动窗口协议最大的不同是,发送方发送分组时,为一个分组都创建了一个定时器。
                当发送方接受到一个分组的确认应答后,取消该分组的定时器,并判断接受该分组后,是否存在由窗口首部为首的连续的确认分组,如果有则向后移动窗口的位置,如果没有则将该分组标识为已接收的乱序分组。当某一个分组定时器到时后,则重新传递这个分组。
            - 在接收方,它会确认每一个正确接收的分组,不管这个分组是按序的还是乱序的,乱序的分组将被缓存下来,直到所有的乱序分组都到达形成一个有序序列后,再将这一段分组交付给上层。
                对于不能被正确接收的分组,接收方直接忽略该分组。
        
    • 阻塞优化算法

        - 慢热启动算法
        - 拥塞避免算法
        - 超时重传算法
        - 快速恢复算法
      

网络层

网络层协议主要实现了不同主机间的逻辑通信功能。

IP 网际协议

IP 网际协议规定了网络层的编址和转发方式,比如说我们接入网络的主机都会被分配一个 IP 地址,常用的比如 IPV4 使用 32 位来分配地址,还有 IPv6 使用 128 位来分配地址。

路由选择协议

路由选择协议决定了数据报从源到目的地所流经的路径,常见的比如距离向量路由选择算法等。

应用层

http

  • HTTP 是超文本传输协议,它定义了客户端和服务器之间交换报文的格式和方式,默认使用 80 端口。它使用 TCP 作为传输层协议,保证了数据传输的可靠性。

  • HTTP 是一个无状态的协议,HTTP 服务器不会保存关于客户的任何信息。

  • HTTP 有两种连接模式,一种是非持续连接,一种持续连接。

    - 非持续连接指的是服务器必须为每一个请求的对象建立和维护一个全新的连接。
    - 持续连接下,TCP 连接默认不关闭,可以被多个请求复用。
      - 采用持续连接的好处是可以避免每次建立 TCP连接三次握手时所花费的时间。
    - HTTP1.0 以前使用的非持续的连接,但是可以在请求时,加上 Connection: keep-alive 来要求服务器不要关闭 TCP 连接。
    - HTTP1.1 以后默认采用的是持续的连接。目前对于同一个域,大多数浏览器支持同时建立 6 个持久连接。
    
  • HTTP 报文

    • 请求报文

      - 第一行是请求行:方法+网络协议+版本
      - 第二行是首部行:用户信息:浏览器内核+版本+系统
      - 请求首部之后有一个空行,这个空行不能省略,它用来划分首部与实体。
      - 第三行是实体主体。
      
      ```
      GET / HTTP/1.1
      User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)
      Accept: */*```
      ```
      
    • 响应报文

      - 第一行叫做状态行:协议版本字段+状态码+状态信息
      - 之后首部行
      - 最后是实体主体。
      
      ```
      HTTP/1.0 200 OK
      Content-Type: text/plain
      Content-Length: 137582
      Expires: Thu, 05 Dec 1997 16:00:00 GMT
      Last-Modified: Wed, 5 August 1996 15:55:28 GMT
      Server: Apache 0.84
      
      <html>
        <body>Hello World</body>
      </html>
      ```
      
    • 首部可以分为四种首部,请求首部、响应首部、通用首部和实体首部。

      - 通用首部和实体首部在请求报文和响应报文中都可以设置,区别在于请求首部和响应首部。
      - 常见的请求首部有 Accept 可接收媒体资源的类型、Accept-Charset 可接收的字符集、Host 请求的主机名。
      - 常见的响应首部有 ETag 资源的匹配信息,Location 客户端重定向的 URI。
      - 常见的通用首部有 Cache-Control 控制缓存策略、Connection 管理持久连接。
      - 常见的实体首部有 Content-Length 实体主体的大小、Expires 实体主体的过期时间、Last-Modified 资源的最后修改时间。
      
  • 缺点

    - HTTP/1.1 默认使用了持久连接,多个请求可以复用同一个 TCP 连接,但是在同一个 TCP 连接里面,数据请求的通信次序是固定的。
    服务器只有处理完一个请求的响应后,才会进行下一个请求的处理,如果前面请求的响应特别慢的话,就会造成许多请求排队等待的情况,这种情况被称为“队头堵塞”。
    队头阻塞会导致持久连接在达到最大数量时,剩余的资源需要等待其他资源请求完成后才能发起请求。
    - 为了避免这个问题,一个是减少请求数,一个是同时打开多个持久连接。这就是我们对网站优化时,使用雪碧图、合并脚本的原因。
    

http2

2009 年,谷歌公开了自行研发的 SPDY 协议,主要解决HTTP/1.1 效率不高的问题。这个协议在 Chrome 浏览器上证明可行以后,就被当作 HTTP/2 的基础,主要特性都在 HTTP/2 之中得到继承。2015 年,HTTP/2 发布。

  • 新特性

    - HTTP/2 是一个二进制协议。在 HTTP/1.1 版中,报文的头信息必须是文本(ASCII 编码),数据体可以是文本,也可以是二进制。HTTP/2 则是一个彻底的二进制协议,头信息和数据体都是二进制,并且统称为"帧",可以分为头信息帧和数据帧。帧的概念是它实现多路复用的基础。
    
    - HTTP/2 实现了多路复用,HTTP/2 仍然复用 TCP 连接,但是在一个连接里,客户端和服务器都可以同时发送多个请求或回应,而且不用按照顺序一一发送,这样就避免了"队头堵塞"的问题。(因为是帧,帧可以对应流,流可以不用按顺序来)
    
    - HTTP/2 使用了数据流的概念,因为 HTTP/2 的数据包是不按顺序发送的,同一个连接里面连续的数据包,可能属于不同的请求。因此,必须要对数据包做标记,指出它属于哪个请求。HTTP/2 将每个请求或回应的所有数据包,称为一个数据流。每个数据流都有一个独一无二的编号。数据包发送的时候,都必须标记数据流 ID ,用来区分它属于哪个数据流。
    
    - HTTP/2 对请求重复的字段做了优化,头信息使用 gzip 或 compress 压缩后再发送。
    
    - 客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就能提高速度了。
    
    - HTTP/2 允许服务器未经请求,主动向客户端发送资源,这叫做服务器推送。使用服务器推送,提前给客户端推送必要的资源,这样就可以相对减少一些延迟时间。这里需要注意的是 http2 下服务器主动推送的是静态资源,和 WebSocket 以及使用SSE 等方式向客户端发送即时数据的推送是不同的。
    
  • 缺点

    - 因为 HTTP/2 使用了多路复用,一般来说同一域名下只需要使用一个 TCP 连接。由于多个数据流使用同一个 TCP 连接,遵守同一个流量状态控制和拥塞控制。只要一个数据流遭遇到拥塞,剩下的数据流就没法发出去,这样就导致了后面的所有数据都会被阻塞。HTTP/2 出现的这个问题是由于其使用 TCP 协议的问题,与它本身的实现其实并没有多大关系。
    

http3

https

  • TLS 握手

    1. 第一步,客户端向服务器发起请求,请求中包含使用的协议版本号、生成的一个随机数、以及客户端支持的加密方法。
    2. 第二步,服务器端接收到请求后,确认双方使用的加密方法、并给出服务器的证书、以及一个服务器生成的随机数。
    3. 第三步,客户端确认服务器证书有效后,生成一个新的随机数,并使用数字证书中的公钥,加密这个随机数,然后发给服务器。并且还会提供一个前面所有内容的 hash 的值,用来供服务器检验。
    4. 第四步,服务器使用自己的私钥,来解密客户端发送过来的随机数。并提供前面所有内容的 hash 值来供客户端检验。
    5. 第五步,客户端和服务器端根据约定的加密方法使用前面的三个随机数,生成对话秘钥,以后的对话过程都使用这个秘钥来加密信息。
    
  • 加密

  • 将http转换为https

    - axios配置
      - baseUrl指定https网址
    
    - meta标签
      <meta http-equiv ="Content-Security-Policy" content="upgrade-insecure-requests">
    
  • SSL 断开如何恢复,一共有两种方法来恢复断开的 SSL 连接,一种是使用 session ID,一种是 session ticket。

    • 使用 session ID 的方式,每一次的会话都有一个编号,当对话中断后,下一次重新连接时,只要客户端给出这个编号,服务器如果有这个编号的记录,那么双方就可以继续使用以前的秘钥,而不用重新生成一把。目前所有的浏览器都支持这一种方法。 但是这种方法有一个缺点是,session ID 只能够存在一台服务器上,如果我们的请求通过负载平衡被转移到了其他的服务器上,那么就无法恢复对话。
    • 另一种方式是 session ticket 的方式,session ticket 是服务器在上一次对话中发送给客户的,这个 ticket 是加密的,只有服务器能够解密,里面包含了本次会话的信息,比如对话秘钥和加密方法等。 这样不管我们的请求是否转移到其他的服务器上,当服务器将 ticket 解密以后,就能够获取上次对话的信息,就不用重新生成对话秘钥了。

DNS 协议

DNS 协议提供的是一种主机名到 IP 地址的转换服务,就是我们常说的域名系统。它是一个由分层的 DNS 服务器组成的分布式数据库,是定义了主机如何查询这个分布式数据库的方式的应用层协议。DNS 协议运行在 UDP 协议之上,使用 53 号端口。
  • 层级结构

    主机名.次级域名.顶级域名.根域名
    
  • 查询

    - DNS 的查询过程一般为,我们首先将 DNS 请求发送到本地 DNS 服务器,由本地 DNS 服务器来代为请求。
    - 从"根域名服务器"查到"顶级域名服务器"的 NS 记录和 A 记录( IP 地址)。
    - 从"顶级域名服务器"查到"次级域名服务器"的 NS 记录和 A 记录( IP 地址)。
    - 从"次级域名服务器"查出"主机名"的 IP 地址。
    
    比如我们如果想要查询 www.baidu.com 的 IP 地址。
      - 我们首先会将请求发送到本地的 DNS 服务器中,本地 DNS 服务器会判断是否存在该域名的缓存。
      - 如果不存在,则向根域名服务器发送一个请求,根域名服务器返回负责 .com 的顶级域名服务器的 IP 地址的列表。
      - 然后本地 DNS 服务器再向其中一个负责 .com 的顶级域名服务器发送一个请求,负责 .com的顶级域名服务器返回负责 .baidu 的权威域名服务器的 IP 地址列表。
      - 然后本地 DNS 服务器再向其中一个权威域名服务器发送一个请求,最后权威域名服务器返回一个对应的主机名的 IP 地址列表。
    
  • 方式

    - 递归查询
      递归查询指的是查询请求发出后,域名服务器代为向下一级域名服务器发出请求,最后向用户返回查询的最终结果。使用递归查询,用户只需要发出一次查询请求。
      一般我们向本地 DNS 服务器发送请求的方式就是递归查询,因为我们只需要发出一次请求,然后本地 DNS 服务器返回给我们最终的请求结果。
      【用户向本地 DNS 服务器请求查询,本地 DNS 服务器递归调用自己最后返回结果是递归查询】
    
    - 迭代查询
      迭代查询指的是查询请求后,域名服务器返回单次查询的结果。下一级的查询由用户自己请求。使用迭代查询,用户需要发出多次的查询请求
      本地 DNS 服务器向其他域名服务器请求的过程是迭代查询的过程,因为每一次域名服务器只返回单次查询的结果,下一级的查询由本地 DNS 服务器自己进行。
      【本地 DNS 向其他域名请求数据查到最终的结果的过程,是迭代】
    
  • 负载平衡

    DNS 可以用于在冗余的服务器上实现负载平衡。因为现在一般的大型网站使用多台服务器提供服务,因此一个域名可能会对应多个服务器地址。
    当用户发起网站域名的 DNS 请求的时候,DNS 服务器返回这个域名所对应的服务器 IP 地址的集合,但在每个回答中,会循环这些 IP 地址的顺序,用户一般会选择排在前面的地址发送请求。以此将用户的请求均衡的分配到各个不同的服务器上,这样来实现负载均衡。
    
  • 为什么使用 UDP 协议

    - DNS 使用 UDP 协议作为传输层协议的主要原因是为了避免使用 TCP 协议时造成的连接时延。
        因为为了得到一个域名的 IP 地址,往往会向多个域名服务器查询,如果使用 TCP 协议,那么每次请求都会存在连接时延,这样使 DNS 服务变得很慢,因为大多数的地址查询请求,都是浏览器请求页面时发出的,这样会造成网页的等待时间过长。
    - 使用 UDP 协议作为 DNS 协议会有一个问题,由于历史原因,物理链路的最小MTU = 576,所以为了限制报文长度不超过576,UDP 的报文段的长度被限制在 512 个字节以内,这样一旦 DNS 的查询或者应答报文,超过了 512 字节,那么基于 UDP 的DNS 协议就会被截断为 512 字节,那么有可能用户得到的 DNS 应答就是不完整的。
    - 这里 DNS 报文的长度一旦超过限制,并不会像 TCP 协议那样被拆分成多个报文段传输,因为 UDP 协议不会维护连接状态,所以我们没有办法确定那几个报文段属于同一个数据,UDP 只会将多余的数据给截取掉。为了解决这个问题,我们可以使用 TCP 协议去请求报文。
    - DNS 还存在的一个问题是安全问题,就是我们没有办法确定我们得到的应答,一定是一个安全的应答,因为应答可以被他人伪造,所以现在有了 DNS over HTTPS 来解决这个问题。
    

image.png

数据结构与算法

image.png

数据结构

数组与矩阵

线性表

- 链表
- 队列
- 栈

  • 概念

    - 结点的度
    - 树的度
    - 叶子结点
    - 分支结点
    - 内部结点
    - 父结点
    - 子结点
    - 兄弟结点
    - 层次
    
  • 二叉树

    - 遍历
      - 前序遍历
      - 中序遍历
      - 后序遍历
      - 层序遍历
    
    - 类型
      - 满二叉树
      - 平衡二叉树
      - 查找二叉树
      - 哈夫曼树(最优二叉树)
      - 线索二叉树
    

- 存储
  - 邻接矩阵
  - 邻接表

- 遍历
  - 深度优先
  - 广度优先

- 最小生成树
  - 普里姆算法
  - 克鲁斯卡尔算法

散列表

广义表

基础

特性

- 有穷性
- 确定性
- 输入值 >= 0
- 输出 >= 1
- 有效性

复杂度

- 时间复杂度
- 空间复杂度

排序

排序算法

  • 插入类排序

    • 插入排序

      时间复杂度空间复杂度
      平均情况O(n^2)O(1)
      最坏情况O(n^2)O(1)
    • 希尔排序

      时间复杂度空间复杂度
      平均情况O(n^1.3)O(1)
      最坏情况O(n^2)O(1)
  • 选择类排序

    • 简单选择排序

      时间复杂度空间复杂度
      平均情况O(n^2)O(1)
      最坏情况O(n^2)O(1)
    • 堆排序

      时间复杂度空间复杂度
      平均情况O(nlog2n)O(1)
      最坏情况O(nlog2n)O(1)
      • 大顶堆
      • 小顶堆
  • 交换类排序

    • 冒泡排序

      时间复杂度空间复杂度
      平均情况O(n^2)O(1)
      最坏情况O(n^2)O(1)
    • 快速排序

      时间复杂度空间复杂度
      平均情况O(nlog2n)(log2n)
      最坏情况O(n^2)(log2n)
  • 其他排序

    • 归并排序

      时间复杂度空间复杂度
      平均情况O(nlog2n)O(n)
      最坏情况O(nlog2n)O(n)
    • 基数排序

      时间复杂度空间复杂度
      平均情况O(n)O(n)
      最坏情况O(n)O(n)
    • 桶排序

      时间复杂度空间复杂度
      平均情况O(n)O(n)
      最坏情况O(n)O(n)

稳定

- 冒泡排序
- 插入排序
- 归并排序
- 基数排序

平台

leetcode

牛客


image.png

Vue

image.png

生命周期

10个生命周期(包括keep-alive)

computed 和 watch 区别

父子组件生命周期钩子函数

- 加载渲染过程
- 父/子组件更新过程
- 销毁过程

组件通信方式

Vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。

模块

Action的作用

与全局 vue 的区别

Vue-router

路由模式

- hash
  - location.hash
  - 使用 URL hash 值来作路由

- history
  - HTML5 History API 和服务器配置

- abstract
  - 发现没有上述可使用的的 API,路由会自动强制进入这个模式.

Vue3

监测机制

- Proxy/Object.defineProperty

- 惰性观察
    在 2.x 版本里,不管数据多大,都会在一开始就为其创建观察者。当数据很大时,这可能会在页面载入时造成明显的性能压力。3.x 版本,只会对「被用于渲染初始可见部分的数据」创建观察者,而且 3.x 的观察者更高效。

- 不可变的 observable

- 更精准的变更通知
    比例来说:2.x 版本中,使用 Vue.set 来给对象新增一个属性时,这个对象的所有 watcher 都会重新运行;3.x 版本中,只有依赖那个属性的 watcher 才会重新运行。

Composition API()

加强typescript支持

性能提升

- 更小巧,更快速
- 摇树优化
- Fragments 和跨组件渲染
- 自定义渲染器

模板引擎

插值

指令

过滤器

SPA/SSR

优化

代码层面

- v-if 和 v-show 区分使用场景
- computed 和 watch 区分使用场景
- v-for 遍历必须为 item 添加 key,且避免同时使用 v-if
- 长列表性能优化
- 事件的销毁
- 图片资源懒加载
- 路由懒加载
- 第三方插件的按需引入
- 优化无限列表性能
- 服务端渲染 SSR or 预渲染

工程化层面

- Webpack 对图片进行压缩
- 减少 ES6 转为 ES5 的冗余代码
- 提取公共代码
- 模板预编译
- 提取组件的 CSS
- 优化 SourceMap
- 构建结果输出分析
- Vue 项目的编译优化

基础 Web 技术

- 开启 gzip 压缩
- 浏览器缓存
- CDN 的使用
- 使用 Chrome Performance 查找性能瓶颈

PAW-渐进式Web应用

- 优点
  - 可以生成桌面小图标,不需要打开浏览器,方便用户访问
  - 通过网络缓存提升页面访问速度,达到渐进式的页面甚至离线访问,提升用户体验
  - 实现类似app的推送功能,生成系统通知推送给用户

- 组成
  - App Manifest(App)
  - Service Worker(重点)
  - Notifications API
  - Push API

原理

v-model

MVVM

数据双向绑定

  • 监听器:Observer 在Vue 2.0 源码中用到 Object.defineProperty() 来劫持各个数据属性的 setter / getter。

    • Object.defineProperty

      - 三个参数
      
      - 共享描述符
        1. configurable:能否修改配置(false 不能被修改)
        2. enumerable:能否被枚举(false 不能被枚举)
        
      - 数据描述符
        3. value:对应值(undefined)
        4. writable:value 能否被赋值(false)
        
      - 存取描述符
        5. get:属性的 getter 函数,如果没有 getter,则为 undefined。当访问该属性时,调用此函数。
        6. set:属性的 setter 函数,如果没有 setter,则为 undefined。当属性值被修改时,调用此函数。
      
  • 解析器:Compile

    解析模板指令,并替换 vue 模板引擎的数据,初始化视图;
    将模板指令对应的节点绑定对应的更新函数,初始化相应的订阅器 Watcher;
    
  • 订阅者:Watcher

    将自己通过 getter 添加到订阅器 dep 中
    通过 dep 通知监听器 Observer 的变化,进而通知解析器 Compile 更新视图。实现 Observer 和 Compile 的绑定
    
  • 订阅器:Dep

    一个组件中的订阅器 Dep 主要来负责收集订阅者 Watcher,当数据变化的时,对应通知订阅者的更新函数。
    

虚拟DOM

- 优缺点

- 实现原理
  - 虚拟抽象 DOM 树
  - diff算法
  - patch

单向数据流

引用数据类型赋值

vm.$set

data为什么是一个函数

渲染到更新整个流程

综上关于详细的 Vue 有太多好的干货文章在「掘金」里了,俺就偷懒。近期也一直在画 Vue 源码的思维导图,加油加油!


image.png

战略性放空...

工程化

image.png

Webpack

原理和作用

构建流程

1. webpack会从入口文件开始打包
2. 记录依赖形成依赖关系树状图
3. 根据依赖关系树状图引进依赖资源
4. 形成一个个chunk(代码块)
5. 各项处理(编译等)== 打包
6. 处理好的资源文件输出出去 == bundle
7. 统称为静态模块打包器

配置

  • loader

    样式:style-loader、css-loader、less-loader、sass-loader等
    文件:raw-loader、file-loader 、url-loader等
    编译:babel-loader、coffee-loader 、ts-loader等
    校验测试:mocha-loader、jshint-loader 、eslint-loader等
    
  • plugin

    UglifyJsPlugin:压缩和混淆代码
    CommonsChunkPlugin:提高打包效率,将第三方库和业务代码分开打包
    html-webpack-plugin:可以根据模板自动生成html代码,并自动引用css和js文件
    DefinePlugin:编译时配置全局变量,这对开发模式和发布模式的构建允许不同的行为非常有用。
    DllPlugin:第三方包的构建,只构建业务代码。
    DllReferencePlugin:引用DllPlugin配置生成的manifest.json文件,manifest.json包含了依赖模块和module id的映射关系。
    
    - 配置 plugins
    
    - 手写一个 plugin
      1.编写一个JavaScript命名函数。
      2.在它的原型上定义一个apply方法。
      3.指定挂载的webpack事件钩子。
      4.处理webpack内部实例的特定数据。
      5.功能完成后调用webpack提供的回调。
      
     编写插件之前要理解compiler和compilation两个对象,以及webpack生命周期的各个阶段和钩子,plugin比loader强大,通过plugin你可以访问compliler和compilation过程,通过钩子拦截webpack的执行。
    

优化

  • 打包构建

    - HMR:一个模块发生变化,只会重新打包这一个模块,极大提升构建速度。
    - babel缓存:在对应的 loader 中开启 cacheDirectory: true
    - 多进程打包:- 多个进程进行并行打包
        在对应 loader 配置 workers
    - dll:对某些库(第三方库:jquery、react、vue...)进行单独打包,需构建 webpack.dll.js 文件。
    
  • 优化代码

    - source-map:一种提供源代码到构建后代码映射技术(通过映射可以追踪源代码错误)
    - 缓存:
      hash:粒度整个项目
      chunkhash:粒度entry的每个入口文件
      contenthash:粒度每个文件的内容
    - tree shaking:去除无用代码,减少代码体积
    - code split:代码切割,提取公共代码
    - pwa:渐进式网络开发应用程序(离线可访问)
    

Vite

Vite 会在本地帮你启动一个服务器,当浏览器读取到这个 html 文件之后,会在执行到 import 的时候才去向服务端发送 Main.vue 模块的请求,Vite 此时在利用内部的一系列黑魔法,包括 Vue 的 template 解析,代码的编译等等,解析成浏览器可以执行的 js 文件返回到浏览器端。

这就保证了只有在真正使用到这个模块的时候,浏览器才会请求并且解析这个模块,最大程度的做到了按需加载。

原理

  • 浏览器原生 ES Module 支持
<div id="app"></div>
<script type="module">
  import { createApp } from 'vue'
  import Main from './Main.vue'
  createApp(Main).mount('#app')
</script>

依赖预编译

  • Esbuild

    你可以理解为,这一步和 Webpack 所做的构建一样,只不过速度快了几十倍。
    - Go 语言
      Esbuild 使用 Go 编写,并且比以 JavaScript 编写的打包器预构建依赖快 10-100 倍。
    
  • 对 CommonJS 分析

插件机制

  • 兼容 Rollup

    一般来说,只要一个 Rollup 插件符合以下标准,那么它应该只是作为一个 Vite 插件: 如果一个 Rollup 插件只在构建阶段有意义,则在 build.rollupOptions.plugins 下指定即可。


image.png

软技能

image.png

反问

1.对我的评价以及改进

2.如何利用自己项目经验和团队能力的优势

3.我主要负责什么,如何突破自己

4.这个岗位的具体要求和职责是什么?应具备哪些能力和素质?

5.技术选型

6.日常生活的一天情况

7.我该如何构建自己的前端体系树

项目

- 难题

- 技术挑战

- 后端

- 测试
    mocha
    jest

生活

1.未来技术规划

2.看什么技术书籍

3.如何学习前端

4.大学印象最深的经历

5.做的最大贡献以及收获

6.个人思考/反思

7.你能将前端作为自己一种热爱的事业嘛

8.兴趣爱好

image.png

思维导图

若是只想要思维导图就就就就来这取就好了~

  • 无敌 HTML image.png

  • 帅气 CSS image.png

  • 阿巴 JS image.png

  • 老大哥浏览器 image.png

  • 外交官网络 image.png

  • 挠头数据结构与算法 image.png

  • 保姆工程化 image.png

  • 寂寞软技能 image.png

最后

因为还是大三小生,有可以改进添加的地方!强烈!烈强!欢迎大家评论补充下,我会用心一直维护更新的!
最后觉得有用就点个赞呗!(顺手)希望大家伙早日拿到心满意足的 offer 噢!
最后最后有没有那种大佬集合的交流群呀,拉拉我呗!

image.png

这样点赞

系列如下:(首发掘金,就没了,小可爱们记得点赞唷!)