你的浏览器不支持canvas

Enjoy life!

我对前端面试的看法 (四)性能与工程化

Date: Author: JM

本文章采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可。

1、TCP

  • TCP(Transmission Control Protocal),传输控制协议
  • 是一种面向连接的、可靠的、基于字节流的传输层通信协议
  • 任何连接的逻辑都可以按以下三步去分析:创建连接、数据传输、终止连接
  • 创建连接就是三次挥手
    • 一开始客户端发送请求,那么服务器端处于Listen监听状态
    • 之后,客户端就会处于SYN_SENT状态,发送SYN seq=x 到服务器端,x的取值是唯一的,随机产生的;
    • 服务器端收到后,就会处于SYN_RCVD状态,就会发送一个响应请求SYN seq=y ACK=x+1 给客户端,告诉客户端我收到你的连接请求了!
    • 当浏览器收到响应后,就会变成ESTABLISHED状态,这只是一端建立连接,另外一端还没有建立连接
    • 所以,客户端会再次返回一个响应给服务器端,我已经建立连接了,你也可以建立连接了,最后服务器端处于ESTABLISHED状态
    • 建立连接成功!
  • 创建连接成功后,就开始传输数据
  • 这里要注意的就是seq=x+1,这个seq number是唯一的,主要是保证分组
  • 比如说,你传输一个比较大的文件,不可能一次性就将文件发送到服务端,这时候,这个大文件就会被分成一小组一小组, 传输的时候,可能会打乱传输,那你通过什么知道某些数据是属于同一个文件,我们就是通过这个序列号来分辨哪些数据属于哪个文件的
  • 到了终止连接,其实就是四次挥手
    • 客户端认为收到的数据已经足够了,就会发送个包给服务器端,告诉它要终止连接,里面有FIN字段,此时客户端处于FIN_WAIT_1状态
    • 服务器端接收到这个包后,就会处于CLOSE_WAIT状态,并发送响应给浏览器端,告诉浏览器,我知道你要关闭连接了!但是我的数据还没有传输完毕,你等一等再关闭连接!
    • 浏览器收到服务器端发来的响应后,就处于FIN_WAIT_2状态
    • 等到服务器端把所有数据全都发送给客户端后,就会发送响应给客户端,我发送完数据给你了,可以关闭连接了。此时,服务器端处于LAST_ACK状态
    • 客户端收到服务器端的响应后,就处于TIME_WAIT状态,此时客户端关闭连接,但是还有服务器端还没有关闭连接
    • 所以,客户端会再发一次响应给服务器端,告诉它我关闭连接了,你也可以关闭连接了。
    • 服务器端收到响应后,就关闭连接
    • 四次握手结束

2、HTTP

  • HTTP(HyperText Transmission Protocal),超文本传输协议。
  • 是一种用于分布式、协作式和超媒体信息系统的应用层协议
  • 请求报文:
    • 请求行:方法(空格)URL(空格)版本(CRLF回车换行)
    • 首部行:字段名:(空格)值(每个字段值结束后都要回车换行)
    • 空一行
    • 实体主体(一般不用),不过遇到post、put方法,传的又是json格式的数据,就会使用这个实体主体传输
  • 响应报文:
    • 状态行:版本(空格)状态码(空格)短语(CRLF回车换行)
    • 首部行:字段名:(空格)值(每个字段值结束后都要回车换行)
    • 空一行
    • 实体主体(有些响应报文不用)

3、状态码

先大分类,并说明每个大分类表示什么,再说一说常用的状态码以及其含义是什么

  • 100 - 199:信息提示
  • 200 - 299: 成功
  • 300 - 399:重定向,需要进一步操作以完成请求
  • 400 - 499:客户端错误提示,请求包含语法错误或者无法完成请求
  • 500 - 599:服务端错误提示,服务器在处理请求的过程中发生了错误
  • 常用状态码:
    • 200:OK,代表请求成功,所请求的资源发送回客户端
    • 201: Created,表示创建了新资源,主要是新增数据成功后返回
    • 202: Accepted,更新成功,主要是更新数据成功后返回
    • 301与302:301 表示永久移动,302表示临时性的移动。
      • 比如:我有一个商城网站,现在有了新的域名,但是老客户记住的只是旧域名,怎么办?如果我 不想使用旧域名,则给一个301状态,然后能识别301语义的客户端,就请收藏我的新链接;而如果我还想用旧域名, 这只是我临时移动,那我就给个302的状态码,能识别302语义的客户端就请继续收藏我的旧链接。
    • 304:Not Modified,代表上次的文档已被缓存,还可以继续使用
    • 401:表示未授权
    • 403:表示被禁止访问
    • 400:Bad Request,表示请求的地址不存在或者包含不支持的参数
    • 404:Not Found,请求资源不存在
    • 405:Method Not Allowed,请求方法对指定的资源不适用
    • 500:Interval Server Error,服务器发生不可预期的错误
    • 503:Server Unavailable,服务器当前不能处理客户端的请求,一段时间后可能回复正常

4、浏览器缓存的头字段有哪些,缓存的逻辑是怎样的?

先回答有哪些头字段,其含义代表什么,常用值是什么,然后再说缓存的逻辑

  • 与浏览器缓存有关的头字段有以下这些:
  • 响应头字段
    • Cache-Control: max-age=60,相对时间,优先级高于 expires
      • 这里是60s,假设用户第一次访问这个页面,那么在这60s以内,页面都会在缓存里
    • expires:绝对是时间,格林尼治时间,缓存的时间界限
    • last-modified:文件最后的修改时间,浏览器会将这个时间缓存下来
    • Etag:将文件内容作为基础,然后经过一系列复杂的算法得到一个字符串,即哈希值,这个值是唯一不变的。除非你的文件内容改变了
  • 请求头字段:
    • if-modified-since:文件最后修改的时间,它保存的值其实就是last-modified的值
    • If-None-Match:就是Etag
  • EtagIf-None-Match 绝对是成对出现
  • Last-ModifiedIf-Modified-Since 也是成对出现
  • 这两队组合都是协商缓存
  • 接下来开始说一说缓存的整个流程
  • 用户第一次访问A页面,那么客户端就会发送请求给服务器端,服务器端就会返回响应给客户端
  • 返回的响应头里会有 Cache-Control: max-age=60expires,Last-modified 以及 Etag 等响应头字段
  • 如果用户在30s的时候,此时还在过期时间之内,再次访问这个页面,浏览器会直接从本地拿数据返回,根本就没有发送请求给服务器端,我们称这类缓存为强缓存
  • 如果用户在61s时,此时已过了过期时间,再访问这个页面,客户端就会发送一个伴随If-None-MatchIf-Modified-Since 等头字段的请求给服务器,这里的话,会有两种情况,分别是:文件修改过以及文件没有修改过
    • 服务器端接收到这个请求后,会将If-None-Match的值和 Etag 的值作比较,以及If-Modified-SinceLast-Modified 的值作比较
      • 如果两组的值都相等,则证明文件没有被改动过,那么直接返回 304 给客户端(这个响应头也包含Cache-Control: max-age=60Last-Modified),浏览器依然可以在本地缓存的文件
      • 如果 If-Modified-SinceLast-Modified 不相等,而If-None-Match的值和 Etag 相等,也可以返回304给客户端,浏览器依然可以在本地缓存的文件
      • 如果 If-Modified-SinceLast-Modified 相等,而If-None-Match的值和 Etag 不相等,或者两组的值都不想等,那么服务器端就会返回新的资源给客户端,其状态码为200
    • 上述所讲的就是协商缓存
  • 下面再说一说状态码200和304的区别:
    • 200:说明可以返回新的资源给客户端
    • 304:告诉客户端,文件没有被修改过,你可以继续使用本地缓存的文件,简单来说,就是服务器端不会有新的资源返回给客户端

简单版:

用户第一次访问,就会向服务器请求资源,并返回头字段:Cache-Controlexpires,Last-modified 以及 Etag

用户第二次访问,会存在两种情况:强缓存和协商缓存

如果还在过期时间内,那么就不会发送请求,直接在缓存里拿资源,这就是强缓存,与强缓存相关的头字段是 Cache-control 和 Expires

如果过了过期时间,就会发送请求给服务器端,服务器端就会比较Etag和If-None-Match的值,Last Modified 和 If-Modified-Since的值。 如果两组值不相等或者 Last-ModifiedIf-Modefied-Since的值相等而EtagIf-None-Match不相等,则证明文件修改了,服务器端就会返回新的资源给客户端,状态码为200 如果两组值相等或者 Last-ModifiedIf-Modefied-Since的值不相等而EtagIf-None-Match相等,则证明文件没有被修改,服务器端就会返回304给客户端,客户端可以继续使用缓存里的资源。

5、DNS

  • 假设你是第一次访问ke.qq.com这个网站,没有缓存。
  • 当你在地址栏中输入这个网址的时候,它不是第一时间就发送http请求,而是要找到对应的IP地址才能发送http请求
  • 那么,获取IP地址的方法就是通过DNS,域名系统查询。
  • DNS (Domain Name System):域名系统
    • 它是应用层的协议,基于UDP协议,而HTTP也是应用层协议,不过HTTP是基于TCP协议
  • ke.qq.com ==》 三级域名.二级域名.顶级域名
  • 根域名服务器
    • 根:管理顶级域名
  • 顶级域名服务器
    • 顶级域名:都是固定的,例如:com,cn,org,net,hk
  • 权限域名服务器
    • 二级域名:一般是自己去买来的,自己去定义的,例如:google,qq,taobao
    • 三级域名:有二级域名后,就可以自己去分配,比如:ke,www
    • 四级域名:有三级域名后,四级域名也可以自己去分配,如:imweb.ke.qq.com

  • DNS有两种查询方式,分别是迭代查询、递归查询
  • 假设,我们要查询ke.qq.com的ip地址
  • 先说说迭代查询:
    • 本机先向本地域名服务器发起查询,如果找到对应的ip地址,那么本地服务器直接将ip地址返回给本机
    • 如果没有找到对应的ip地址,那么本地域名服务器就会向根域名服务器发起查询,如果找到对应的ip地址,那么根域名服务器则通过本地域名服务器,将ip地址返回给本机
    • 如果在根域名服务器没有找到ip地址,那么本地域名服务器就会向顶级域名服务器发起查询,如果找到对应的ip地址,那么顶级域名服务器就会通过本地域名服务器将ip地址返回给本机
    • 如果在顶级域名服务器也没有找到ip地址,那么本地域名服务器就会向权限域名服务器发起查询,找到对应的ip地址,权限域名服务器就会通过本地域名服务器将ip地址返回给本机
  • 接着说说递归查询
    • 首先,本机先向本地域名服务器发起查询,如果找到ip地址,那么本地服务器就会将ip地址直接返回给本机,
    • 如果没有找到,那么本地域名服务器就会向根域名服务器发起查询,如果找到ip地址,根域名服务器先将ip地址告诉本地服务器,本地服务器再将ip地址返回给本机,
    • 如果没有找到,那么根域名服务器就会向顶级域名服务器发起查询,如果找到ip地址,顶级域名服务器先将ip地址告诉根域名服务器,根域名服务器再告诉本地服务器,本地服务器再将ip地址返回给本机,
    • 如果没有找到,那么顶级域名服务器就会向权限域名服务器发起查询,找到ip地址,权限域名服务器就会告诉顶级域名服务器,顶级域名服务器告诉根域名服务器,根域名服务器再告诉本地服务器,本地服务器再将ip地址返回给本机,

  • 简单版
  • 假设ip地址在顶级限域名服务器找到
  • 迭代,就像for循环一样,做完一件事情才做另外一件事情。dns迭代查询的过程如下:本地域名服务器直接向顶级限域名服务器发起请求,顶级域名服务器借助本地域名服务器返回ip地址给本机
  • 对于递归查询来说,则是本地域名服务器经过根域名服务器再到顶级域名服务器,顶级域名服务器借助根域名服务器和本地域名服务器返回ip地址给本机

6、网络体系结构

  • TCP/IP四层协议:(从上往下)
    • 应用层:DNS,HTTP,SMTP,POP3,IMAP
    • 运输层:TCP,UDP
    • 网际层:IP
    • 网络接口层:物理网络

  • 五层协议
    • 应用层:DNS,HTTP,SMTP,POP3,IMAP
    • 运输层:TCP,UDP
    • 网际层:IP
    • 数据链路层
    • 物理层

  • OSI 的七层协议:
    • 应用层
    • 表示层
    • 会话层
    • 运输层
    • 网络层
    • 数据链路层
    • 物理层

7、从输入地址到返回请求

  • 我是分两部分去理解
  • 第一部分:输入请求,即客户端到服务器端的过程
  • 输入请求后,先通过DNS找到对应的IP地址,然后才发送HTTP请求给服务器端。
  • 在发送给服务器端的过程中会先经历一次逻辑网络(TCP/IP),再到物理网络,最后再经历一次逻辑网络,最终请求到达服务器端
  • 服务器端拿到这个包后,就会拆包,对这个包进行一系列的操作
  • 第二部分:返回响应,即服务器端到客户端的过程
  • 服务器端对传来的包处理完后,又重新打包,发送HTTP请求給客户端,其过程与第一部分说的过程差不多

8、浏览器和渲染引擎

  • 浏览器有以下大模块:HTML解释器,CSS解释器,布局,JS引擎,网络,存储(缓存),2D/3D图形,音频和视频,图片解码器
  • 其中:HTML解释器、CSS解释器、布局、JS引擎我们称之为渲染引擎
  • 每个浏览器的渲染引擎都不一样
    • Chrome:Blink
    • Edge/IE:Trident
    • Safari:Webkit
    • Firefox:Gecko
    • Opera:Blink

9、HTML如何解析成DOM树

  • HTML形成DOM的过程如下:
    • HTML经过词法解析成最小单元 token,然经过语法解析,然后在复杂的语法基础上扫描每一个单元,最后形成DOM树

10、说说渲染过程

  • HTML经过解析形成DOM树
  • css经过解析形成样式规则
  • DOM树和样式规则结合起来形成渲染树(Render Tree)
  • 然后进行Layout,布局
  • 布局完后,就开始Painting,绘制
  • 绘制完后,就会display,展现给用户看
  • 整个流程有一大特点,就是边下载边解析边渲染
    • 比如说,一个html文件有50kb,它不是等50kb都下载完才开始解析渲染,它可能到了8kg就开始解析渲染了
  • DOM树和render树是动态的,是会变化的
    • 比如说,当遇到style,样式表de时候,那么就会再走css解析成样式规则这个流程,再结合与DOM结合成render树
    • 不过,当DOM 树遇到js的时候,很可能会阻塞解析。
      • 因为,js可以直接操作dom,但是你又不知道它是如何操作dom的
      • 所以,要等到js处理完DOM后,才可以继续开始解析和渲染

11、说说DOM树和渲染树

  • 一般情况下,DOM树和渲染树是一一对应的,不过也有例外,比如:
  • 不可显示的元素在DOM树中有,但在render树中却没有,例如:head元素、display:none的元素
  • 还有一种就是定位元素,定位元素只是render树里的一个占位符,它会到其他地方去渲染
  • 以上其实可以给我们一些启发:
    • 比如说:在操作DOM的时候,我先让其display:none,等操作完了,才让其显示,这明显减少了对render树的干扰,从而也提高了painting的效率
    • 比如说:在处理一些复杂的动画的时候,为这个动画设置绝对定位,这也可以减少了对render树的干扰,从而也提高了painting的效率

12、重排和重绘

先说说重排和重绘各自是什么,什么会导致重排、重绘,有什么可以减少重排和重绘带来的影响

  • 重排(reflow),一般涉及到几何属性,比如:
    • 页面第一次渲染
    • 浏览器窗口尺寸变化
    • 元素的位置和尺寸变化
      • 通过display: none 隐藏 DOM 节点,会导致重排和重绘
      • 通过visibility: hidden 隐藏 DOM 节点,只会导致重绘,因为其没有影响布局
    • 新增和删除可见元素
      • 对 DOM 节点进行操作,添加、删除、更新 DOM 节点都会导致重排
    • 内容改变
    • 光标 :hover 、进入文本输入框、修改浏览器的字体都会导致重排
  • 重绘(repaint),一般指color、backgroud-color等属性的改变
  • 我们要知道:重排一定会引起重绘,而重绘不一定会引起重排

  • 如果我们要对css属性用js进行修改,一定要连续修改,而不是断续修改
  • 如果读取到某些属性,都会引发浏览器立即重新渲染,所以我们要用一个变量将其存储起来,需要的时候再调用
    • 这些属性有:offset系列,scroll系列,client系列 以及 getComputedStyle()
  • 如果是用通过stylecss 属性进行一个个修改,倒不如用 classjs 里是 className) 或者 cssText
  • DOM离线更新,比如:
    • 操作 DocumengFragment对象,完成后再把这个对象添加到DOM中;
    • 使用 cloneNode() 方法,在克隆的节点上进行操作,然后再用克隆的节点替换原始的节点

13、从输入地址到页面渲染

  • 当用户在地址栏输入地址后,先判断缓存里是否有所要请求的资源,
  • 如果缓存里有,就直接在缓存里拉取资源
  • 如果没有,才会向服务器发送HTTP请求
  • 在发送HTTP请求之前,先通过DNS系统查询IP地址
  • 查询到ip地址后,再送HTTP请求;
  • http请求发送成功后,会通过TCP建立连接,然后通过TCP传输数据,等数据传输完毕后,TCP关闭连接
  • 当HTML有了之后,就会被解析成DOM树,如果有css文件,那么css也会被解析成一定的规则
  • 然后DOM树和css规则联系在一起,形成渲染树,然后开始layout,布局
  • 布局完成后,就开始绘制页面,最终将页面内容呈现给用户

14、讲讲网页性能指标

  • 在打开页面的时候,会经历以下这5个过程:
  • 开始请求 ===》 获取首字节 ===》 页面开始展示 ===》 首屏内容加载完成 ===》 全部加载完成
  • 主要的性能指标是获取首字节、页面开始展示、首屏内容加载完成。
  • 开始请求的时间点我们可以通过 performance.timing.navigationStart 获取
  • 获取首字节的时间点我们可以通过 performace.timing.responseStart 获取
  • 页面开始展示的时间点,我们称其为白屏时间,先说说如何计算白屏时间吧:
    • 白屏时间 = 页面开始展示的时间点 - 发起请求的时间点
    • 我们会在title标签之后用script标签写一段js代码,通过 Date.now 获取发起请求时的时间点,称其为startTime;
    • 在head标签的最后,也是用过Date.now获取页面开始展示的时间点,称其为endTime
    • 最后,将endTime 减去 startTime即可
  • 除此之外,我们还可以用 endTime 减去 performance.timing.navigationStart,也可以获取白屏时间
  • 不滚动屏幕能看到的内容加载完成的时间称之为首屏时间,计算首屏时间有三种方法:
    • 首屏幕块标签标记法:将结束点放在首屏内容的最后一个模块之后
    • 统计首屏内加载最慢的图片的时间:即遍历所有加载的图片的onload事件,把最后触发的onload的Date.now()减去
    • 自定义首屏内容计算法:只考虑页面主要DOM,忽略图片资源加载情况,只考虑首屏模块而非严格的首屏线上的内容

15、有没有做过性能优化,都有哪些手段?

  • 说到性能优化,我们要知道客户端与服务器端间的关系:客户端发送请求给服务器端,然后服务器端会返回响应给客户端,
  • 其实这个过程很想货车运输货物,当时耗时越短越好!
  • 因此,我们要知道在哪些地方是最费时间的,才能去改良,以减少耗时。
  • 我们可以从服务器端以及数据传输的角度进行性能优化:
  • 减少http请求数:一次只发送1个请求肯定会比1次发送10个请求所得到的响应要快
    • 包括小图片合并成雪碧图或者使用iconfont
    • js、css合并
  • 减少资源体积:如果传送的资源体积少了,那么耗时肯定会少
    • 精简代码
    • 压缩js、css、图片,就像webpack里的有专门压缩js、css的功能
  • 提高网络传输:可以想象,速度越快,耗时不就越少了。
    • 使用浏览器缓存:减少了冗余的数据传输,减少了服务器的负担
    • 使用cdn(Content Delivery Network,内容分发网络):通过将静态资源缓存到离用户很近的相同网络运营商的CDN节点上,使用户可以就近取得所需的内容,解决网络堵塞状况,提高用户访问网站的响应速度。
  • 不要在html中缩放图片
    • 就是:你的图片本身是多大就多大,不要故意去缩放,因为解析器要重新计算,比较麻烦
  • 如果要创建大量的节点,不要直接在循环将节点逐个添加到父元素里,要么将这些节点全部放在str里,要么将这些节点全部放在fragemnt里,最后一次性将str或者fragment添加到父元素里

16、nodejs

  • nodejs的出现,打破了javascript只能在客户端运行的常规,现在javascript也能在服务器端上运行了。
  • NodeJS是基于事件驱动和无阻塞的,所以非常适合处理并发请求
  • nodejs的应用场景:搭建服务器、应用开发、构建工具。。。
  • nodejs的缺点就是:一旦报错,就会退出整个应用程序

17、减少页面加载时间

  • 优化图片
  • 图像格式的选择,gif:提供颜色较少,可用在一些对颜色要求不高的地方
  • 减少http请求(文件合并压缩,图片合并)
  • 图片最好设置好宽度高度,因为如果浏览器没有找到这两个属性,就要一边下载,一遍计算大小; 如果一个页面有很多图片要下载,那么浏览器就要不断调整页面,不但影响页面加载速度,也会影响用户体验
  • 4.网址后加斜杠(如www.campr.com/目录,会判断这个“目录是什么文件类型,或者是目录。)

18、说一说get和post

先说是什么,接着说有什么特点

  • get 和 post 都是发送请求的方法
  • get
    • 传递参数的方式:将参数放置在url上,作为查询语句
      • 在ajax里,如果是get方法,所发送的数据直接是null
    • 其实这种方法有很大的局限:首先传递的数据不能过多,除此之外,比较容易泄密
      • 传递的参数需要用encodeURIComponent 加密,以及用 decodeURIComponent 解密
    • get方法:很少用来传递数据,一般都是获取数据
    • get 请求可被缓存
  • post
    • 传递参数的方式:将参数存放在报文的实体主体里
      • 在ajax里,如果是post方法,则发送的数据直接是你要发送给服务器的数据,这里简称data吧
    • 这个方法相对于get方法来说,发送的数据量较大
    • post 方法一般是传递数据,例如添加数据、修改数据;并且post传递的数据格式不限
    • 如果是使用Post发送请求,最好按照实际的数据格式设置请求头Content-Type
    • post 请求不可被缓存

  • 用途不一样:get用来获取数据,post用来传送数据
  • 传递参数的方式不一样:get放在url的查询语句中,post放在报文的实体主体里
  • 传递参数的长度不一样:get有限制,post无限制
  • 缓存:get请求可被缓存,post请求不可被缓存
  • 参数格式:get的参数要经过encodeURIComponent 加密,decodeURIComponent 解密;post格式不限,不用加解密
  • 安全方面:post请求较之get请求要安全得多

19、讲讲模块化

  • 如果一个js文件里有上千行代码,想想就可怕!所以,这也是模块化的由来
  • 模块化的意思就是:将相同的功能的代码放到一个js文件里,分块管理
  • 常常都说模块化和依赖
  • 比如说,你引用了jquery,那么你就是依赖了jquery
  • 所以,模块化绝对会和依赖联系在一起
  • 对于模块化的话,有两个问题必须注意,它们是命名冲突和变量污染。解决这两个问题的方法就是创建命名空间
  • 我们有三种方法创建命名空间,分别是:前缀命名空间、对象命名空间、IIFE(立即执行函数表达式)
    • 前缀命名空间:主要是以模块名作为变量或者函数的前缀,这个方法依旧保留大量全局变量,治标不治本
    • 对象命名空间:就是将变量和函数存在一个变量里,我们可以通过 对象.xxx 的访问变量或者调用函数, 不过有可能会导致调用链过长,同时,这个方法将所有的变量和方法都暴露出来,根本无私隐可言
    • IIFE:创建一个私有作用域,函数和变量当放置在这个私有作用域里,并且可以提供对外接口,提供一些属性和方法供外调用; 这个方法的好处在于:既可以创建私有变量,也解决了命名冲突、变量污染
  • 对于模块化而言,我是在nodejs里用得比较多,因为最近都在研究nodejs。
  • nodejs的模块化是遵循 CommonJS的:每一个文件都是一个模块,通过module.exports暴露模块,通过require引入模块
  • 不过 CommonJs只适用于nodejs服务端,因为文件是存储在本地硬盘,读取速度较快,可以同步加载模块;
  • 但是 CommonJs 并不适用于浏览器端,因为文件都要通过网络去加载,如果用同步加载,既耗时也会阻塞页面
  • 所以 浏览器端需要异步加载所需模块,那就是AMD,主要基于define定义模块,require 调用模块;我们需要下载require.js才能实现。

20、有没有了解过有哪些构建工具

  • Grunt,Gulp,Webpack
  • Grunt:
    • 基于Node,上手容易,插件齐全,社区活跃
    • 缺点:配置繁琐,每次操作都是读写文件,很慢
  • Gulp:
    • 配置简单,基于文件流操作,相对Grunt来说较快
  • Webpack:定位就是一个打包工具,核心理念:对打包进行一系列的优化
    • 任何文件都可以作为模块,打包体积更小,打包更快,默认支持AMD, CommonJS, ES6 Modules

21、测试

  • 关于测试呢我只实践过一次,就是给自己写的一个工具库写测试,用的是Jest框架。
  • 测试的话主要涉及到几个概念,一个断言,用来表达一种预期,一个是测试用例,还有一个是TDD,测试驱动开发
  • 传统的开发呢是重产品的,主要流程是分析需求,调试开发及测试发布
  • 而TDD的话重在重构,分析需求后是任务和模块的拆解,然后编写测试用例,再快速构建代码,这时候代码质量可以很差,
  • 但只要能让测试代码通过即可,目的是能提供给别人用的接口,之后才是重构,即提高代码质量,这时候接口完善了, 代码质量提高了,便可进行功能测试与发布

22、tcp和udp


对于本文内容有问题或建议的小伙伴,欢迎在文章底部留言交流讨论。