- 1、TCP
- 2、HTTP
- 3、状态码
- 4、浏览器缓存的头字段有哪些,缓存的逻辑是怎样的?
- 5、DNS
- 6、网络体系结构
- 7、从输入地址到返回请求
- 8、浏览器和渲染引擎
- 9、HTML如何解析成DOM树
- 10、说说渲染过程
- 11、说说DOM树和渲染树
- 12、重排和重绘
- 13、从输入地址到页面渲染
- 14、讲讲网页性能指标
- 15、有没有做过性能优化,都有哪些手段?
- 16、nodejs
- 17、减少页面加载时间
- 18、说一说get和post
- 19、讲讲模块化
- 20、有没有了解过有哪些构建工具
- 21、测试
- 22、tcp和udp
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
值
Etag
和If-None-Match
绝对是成对出现Last-Modified
和If-Modified-Since
也是成对出现- 这两队组合都是协商缓存
- 接下来开始说一说缓存的整个流程
- 用户第一次访问
A
页面,那么客户端就会发送请求给服务器端,服务器端就会返回响应给客户端- 返回的响应头里会有
Cache-Control: max-age=60
,expires
,Last-modified
以及Etag
等响应头字段- 如果用户在30s的时候,此时还在过期时间之内,再次访问这个页面,浏览器会直接从本地拿数据返回,根本就没有发送请求给服务器端,我们称这类缓存为强缓存
- 如果用户在61s时,此时已过了过期时间,再访问这个页面,客户端就会发送一个伴随
If-None-Match
和If-Modified-Since
等头字段的请求给服务器,这里的话,会有两种情况,分别是:文件修改过以及文件没有修改过
- 服务器端接收到这个请求后,会将
If-None-Match
的值和Etag
的值作比较,以及If-Modified-Since
和Last-Modified
的值作比较
- 如果两组的值都相等,则证明文件没有被改动过,那么直接返回 304 给客户端(这个响应头也包含
Cache-Control: max-age=60
和Last-Modified
),浏览器依然可以在本地缓存的文件- 如果
If-Modified-Since
和Last-Modified
不相等,而If-None-Match
的值和Etag
相等,也可以返回304给客户端,浏览器依然可以在本地缓存的文件- 如果
If-Modified-Since
和Last-Modified
相等,而If-None-Match
的值和Etag
不相等,或者两组的值都不想等,那么服务器端就会返回新的资源给客户端,其状态码为200- 上述所讲的就是协商缓存
- 下面再说一说状态码200和304的区别:
- 200:说明可以返回新的资源给客户端
- 304:告诉客户端,文件没有被修改过,你可以继续使用本地缓存的文件,简单来说,就是服务器端不会有新的资源返回给客户端
简单版:
用户第一次访问,就会向服务器请求资源,并返回头字段:Cache-Control
,expires
,Last-modified
以及 Etag
;
用户第二次访问,会存在两种情况:强缓存和协商缓存
如果还在过期时间内,那么就不会发送请求,直接在缓存里拿资源,这就是强缓存,与强缓存相关的头字段是 Cache-control 和 Expires
如果过了过期时间,就会发送请求给服务器端,服务器端就会比较Etag和If-None-Match的值,Last Modified 和 If-Modified-Since的值。
如果两组值不相等或者 Last-Modified
和 If-Modefied-Since
的值相等而Etag
和If-None-Match
不相等,则证明文件修改了,服务器端就会返回新的资源给客户端,状态码为200
如果两组值相等或者 Last-Modified
和 If-Modefied-Since
的值不相等而Etag
和If-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()
- 如果是用通过
style
对css
属性进行一个个修改,倒不如用class
(js
里是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的话重在重构,分析需求后是任务和模块的拆解,然后编写测试用例,再快速构建代码,这时候代码质量可以很差,
- 但只要能让测试代码通过即可,目的是能提供给别人用的接口,之后才是重构,即提高代码质量,这时候接口完善了, 代码质量提高了,便可进行功能测试与发布