一:preload和prefetch
特点和区别
preload特点:
1.preload加载的资源是在浏览器渲染机制之前进行处理,并且不会阻塞onload事件.
2.preload支持加载多种类型的资源,并且可以加载跨域资源。
3.preload加载的js其加载和执行的过程是分离的。即preload会预加载相应的js,待到需要时自行去调用。
prefetch特点:
1、prefetch加载的资源可以获取非当前页面所需要的资源,并且将其放入缓存至少5min(无论资源是否可以缓存);并且,当页面跳转时,未完成的prefetch请求不会被中断。
对比:
1.preload和prefetch都没有同域名的限制。Preload不添加crossorigin被下载两次。
2.preload主要用于预加载当前页面需要的资源,是告诉浏览器页面必定需要的资源,浏览器一定会加载这些资源;prefetch主要用于加载将来页面可能需要的资源,浏览器不一定会加载这些资源。
3.不论资源是否可缓存,prefetch会存储在net-stack cache中至少5分钟。
4.preload需要使用as属性指定特定资源类型以便浏览器为其分配一定的优先级,并能够正确加载资源;html/css资源的优先级最高,font优先级为highest/high;图片如果出现在视口中,则优先级为high,否则为low。Prefetch优先级最低。如果as不写,那么会当做异步请求处理。
5.有两种方法去使用preload和prefetch:
(1)用link标签的ref属性:
<link ref="preload" as="script/style/image/font/fetch/document/audio/video" href="test.js" οnlοad="handleOnload()" οnerrοr="handlepreloadError()" crossorigin="anonymous/use-credentials">
<link ref="prefetch">
(2)在http响应头中加上preload字段。
preload/prefetch使用案例:
1.提前加载字体文件:由于字体文件必须等到cssom构建完成并且作用到页面元素时,才会加载,会导致页面字体样式闪动。所以要用到preload显示告诉浏览器提前加载。假如字体文件在css生效之前下载完成,则可以完全消灭页面闪动问题。
2.使用preload预加载第二屏的内容。在用户浏览完首屏内容滚动时能够更快的看到次屏的内容。
3.在页面加载完后,可分析页面上的所有链接,预判断用户可能会点击的页面,分析提取下一跳转页面的资源(使用prefetch),浏览器会在空闲时间进行加载,当一用户点击链接命中了缓存,这有效提升下一页面的首屏渲染时间。
4.对于商品列表页面,当鼠标停留在某个商品时,可分析商品详情页所需要的资源并提前开启preload加载,预测用户的行为并做些预加载,点击命中率更高,preload可立即加载资源,有效提升缓存命中率。
二:service worker
使用场景:
1.后台同步:启动一个service worker,即使没有用户访问特定站点,也可以同步更新缓存。
2.响应推送:向用户发送一条信息通知新的内容可用。
3.响应来自其他源的资源请求。
4.集中接受计算成本高的数据更新,比如地理位置和陀螺仪信息,这样,多个页面就可以利用同一组数据。
5.在客户端进行CoffeeScript/LESS/CJS/AMD等模块编译和依赖管理(用于开发)。
6.后台服务钩子。
7.自定义模板用于特定URL模式。
8.性能增强,比如预取用户可能需要的资源。
service worker基本特征
1.无法操作dom.
2.只能使用https和localhost.
3.可以拦截全站请求从而控制应用。
4.与主线程独立不会被阻塞(不要在应用加载时注册sw)
5.完全异步,无法使用xhr和localStorage.
6.一旦被install,就永远存在,除非uninstall.
7.独立上下文.
8.响应推送.
9.后台同步.
10.是事件驱动的worker,生命周期与页面无关,页面未关闭时,sw可退出;没有关联页面时,sw可启动。
service worker生命周期
1.注册:register。client端发起register注册一个service worker,另外需要一个sw.js文件处理sw逻辑。注册后,将作用于整个域内用户可访问的url或者其特定子集。
2.下载:用户首次防卫sw控制的网站或者页面时,sw会立刻被客户端下载。
在以下情况汇总将会触发更新:
(1)前往作用域内页面的导航。
(2)在sw上的一个事件被触发且过去24h没有被下载。
3.安装:install。如果是首次启动sw,sw会尝试安装。
如果现有sw已启动,新版本会在后台安装,但不会被激活,这个时序称为worker in waiting。直到所有已加载的页面不再使用旧sw才会激活新的sw。只要页面不再依赖旧sw,新的sw会被激活(成为active worker).
4.激活:activate。触发时可以清理旧缓存和旧的sw关联的东西。
ps:oninstall和onactivate完成前需要一些时间,sw提供了waitUntil方法,当oninstall或者onactivate触发时被调用,接受一个promise。在这个promise被成功resolve之前,功能性事件不会分发到sw。
service worker与页面的通信:
1.页面向service worker:发送navigator.serviceWorker.active.postMessage(xx);接收this.addEventListener('message',function(event){console.log(event.data)})。
2.service worker向页面:发送this.addEventListener('message',function(event){event.source.postMessage(xx)});接收navigator.serviceWorker.addEventListener('message',function(event){console.log(event.data)});
三:http请求格式和各种字段含义?
https://www.cnblogs.com/linliquan/p/11362336.html
四:从输入url到看到页面的过程
1.浏览器向服务器发送请求解析域名相对应的IP地址。
2.浏览器根据IP地址和默认的80端口,浏览器和服务器建立TCP连接。
3.服务器响应http请求,给浏览器返回html文件。
4.释放TCP连接。
5.浏览器解析html并显示文本。
五:浏览器渲染的过程:
1.浏览器将html解析成一个html树。ps:深度解析:当前节点和下面的子节点都遍历完以后,才会遍历兄弟节点。
2.将css解析成css树。
3.将dom树和css树结合起来,生成render树。每一个dom节点都有attach方法,接收样式信息,返回一个render对象,这些render对象就组成了render树。
4.根据render树,开始布局,确定每个dom在显示屏上面的位置坐标。
5.调用paint方法,进行绘制。
浏览器渲染是一个渐进的过程,为了达到更好的用户体验,渲染引擎会尽快将内容显示在屏幕上。不会等到html文档解析完以后才开始构建render树。
html树、css树、render树不是相互独立的,会有交叉,一边加载,一边渲染的工作现象。
六:请求报文和响应报文
请求:
General:
1.Request URL:请求的url
2.Request Method:请求的方法
3.Status Code:服务器返回的状态
4.Remote Address:请求的
5.Referral Policy:发送Referral的策略,根据Referral(该字段记录来源地址)限制一些接口只能本网站才能调用。
请求报文里面包含:
1.请求行:
请求行分为3个部分:
(1)请求方法:get/post/put/delete
(2)请求URL:由协议://端口/路径组成
(3)HTTP协议版本
2.请求头
(1)Host:服务器地址
(2)User-Agent:发送请求的客户端名称
(3)Connection:连接的相关属性比如keep-alive即保持连接
(4)Accept:通知服务器可以发送的编码格式
(5)Accept-Encoding:通知服务器可以发送的数据压缩格式
(6)Accept-Language:通知服务器可以发送的语言
(7)Referre:浏览器告诉服务器来源地址。
还有其他的token信息等
3.空行:表示请求头传输完毕。
4.请求体
响应报文里面包含:
1.状态行
(1)http版本
(2)状态码
(3)状态码的详解
2.响应头:
(1)Access-Control-Allow-Credentials:是否可以将请求的响应暴露给页面,如果是true表示可以,其他不可以。
(2)Access-Control-Allow-Origin:设置允许跨域的域名或ip。
(3)Content-Type:响应正文的类型。
(4)Content-Length:响应正文的长度。
(5)Content-Charset:响应正文使用的编码。
(6)Content-Encoding:响应正文使用的数据压缩格式。
(7)Accept-Ranges:值为bytes/none。bytes表示服务器接收范围请求,即我们可以做断点下载的功能。
(8)Date:消息发送的时间。使用Date与当前时间进行比较,若响应中的日期值比较早,就可以认为是来自缓存的。
(9)Age:当代理服务器用自己缓存的实体去响应请求时,实体从产生到现在经过多长时间了。通过Age来分辨出这条响应的使用期。
(10)Transfer-Encoding:chunked。分块传输。长连接时,不设置Content-Length字段时,通过此字段来使Recipient正确得知乡邻两次请求的响应内容的分界位置。
(11)Cache-Control:设置强缓存还是协商缓存。
3.空行:表示响应头结束。
4.响应数据
七:一次完整的http请求的7个步骤:
1.浏览器和服务器建立TCP连接
2.浏览器向服务器发送请求命令行
3.浏览器向服务器发送请求头
4.服务器向浏览器发送响应头
5.服务器向浏览器发送响应体
6.服务器向浏览器发送空行
7.关闭TCP连接
八:http1.0和http2.0的区别:
1.http2.0实现多路复用,即连接共享。能够在一个TCP上并行进行任意数量的双向数据量。
2.头部压缩。
3.服务器推送:服务端推送是一种在客户端请求之前发送数据的机制。根据preload修饰资源,可以预请求。
4.二进制分帧。在应用层和传输层之间增加一个二进制分帧层,突破了HTTP1.1的性能限制、改进传输性性能。
九:强缓存和协商缓存
1.强缓存:通过response header中的Cache-Control:maxa-age=xx,public/private,immutable/no-cache/no-store。
public:在xx秒之内,客户端和代理服务器都缓存。如果用户有刷新,那么就重新向服务器发送请求。
private:在xx秒之内,客户端缓存,代理服务器不缓存。如果用户有刷新,那么久重新向服务器发送请求。
immutable:在xx秒之内,客户端缓存。如果用户有刷新,也不向服务器发http请求。
no-cache:跳过强缓存,不妨碍协商缓存。
no-store:不缓存,即没有强缓存没有协商缓存,每次都是重新向服务器发请求。
强缓存的步骤:
1.第一次请求时,缓存中没有该信息,直接请求文件
2.服务器返回文件,并且response header中返回Cache-Control和max-age=xx
3.再次请求时,判断max-age是否过期,如果没有过期就直接读取本地缓存,如果过期就进行协商缓存。
协商缓存的步骤:
1.浏览器第一次发送请求时,服务器response header中返回Last-Modified和ETag的值,浏览器存下文件和两个值。
2.浏览器下次请求时,request header里面自动添加If-Modified-Since(即第一步中的Last-Modified)和If-None-Match(即第一步中的ETag).文件修改后会新生成一个ETag。服务器收到请求后,将文件的Last-Modified、ETag和浏览器传过来的If-Modified-Since、If-None-Match
进行对比,如果一致,就返回304表示未修改;如果有改变,就返回200新的文件。
十:cooke、sessionStore、localStorage的区别?
1.存储大小.
cookie:4k。
sessionStorage和localStorage:5M。
2.数据有效期.
cookie:一般由服务器生成,可以设置失效时间;若没有设置时间,那么关闭浏览器时cookie失效;若设置了时间,cookie
会存放在硬盘里,过期才失效。
sessionStorage:仅在当前浏览器窗口关闭之前有效,关闭页面或者浏览器就会被清除。
localStorage:永久有效,窗口或者浏览器关闭,也会一直保存,除非手动永久清除。
3.作用域。
cookie:在所有同源窗口中都是共享的。
sessionStorage:在同一个浏览器窗口是共享的(不同浏览器的同一个页面不是共享的)。
localStorage:在所有同源窗口中都是共享的。
4.通信。
cookie:在每次http请求中,cookie会在浏览器和服务器之间来回传递。
sessionStorage和localStorage:仅仅保存在客户端,不参与和服务器的通信,不会自动把数据发送给服务器,仅仅保存在本地。。
5.易用性。
cookie:需要自己进行封装才能获取。
sessionStorage和localStorage:使用setItem和getItem进行读取。
十一:程序、进程、线程的区别和联系?
程序是一组指令的有序集合,它本身没有任何运行的含义,它只是一个静态的实体。
进程和线程都是一个时间段的描述,是CPU工作时间段的描述,是动态的,进行和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。进程和线程的颗粒大小不同。
进程是一个动态的实体,它有自己的生命周期,它因创建而产生,因调度而运行,因等待资源或事件而被处于等待状态,因完成任务而被撤销,反映了一个程序在一定的数据集上运行的全部动态过程。
进程和程序不是一一对应的,一个程序执行在不同的数据集上就成为不同的进程,可以用进程控制块来唯一的标识每个进程。进程就是上下文切换的程序执行时间总和=CPU加载上下文+CPU执行+CPU保存上下文。一个程序至少包含一个进程,一个进程至少包含一个线程。
进程和线程的区别和联系有:
(1)进程是资源分配的最小单位,线程是CPU调度的最小单位。
(2)线程的划分尺度小于进程。线程是进程的一个实体,线程自己基本不拥有系统资源,只拥有一点在运行中必不可少的资源。
(3)进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而提高了程序的运行效率。
(4)一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行。
十二:防抖和节流:
防抖是指触发事件后,在n秒内函数只能执行一次。如果在n秒内又触发了事件,则会重新计算函数执行时间,即在不触发的n秒后再执行函数。用setTimeout来实现。
防抖的使用场景:input输入框进行搜索、window的resize。
防抖:
function debounce(func, delay) {
let timeout;
return function () {
clearTimeout(timeout);//如果持续触发 ,会清除定时器,定时器的回调就不会执行
timeout = setTimeout(() => {
func.apply(this, arguments);
}, delay)
}
}
box.onmousemove = debounce(function (e) {
console.log(e)
box.innerHTML = `${e.clientX},${e.clientY}`
}, 1000)
节流是指连续触发事件但是在n秒中只执行一次函数,即n秒执行一次函数。频繁触发事件,但是事件是在一定频率发生。节流会稀释函数的执行频率。实现节流一般有两种方式,分别是时间戳和定时器。
节流的使用场景:不断点击按钮或者mousedown、监听滚动事件来进行加载更多的操作。
节流:
function throttle(func, delay) {
let run = true;
return function () {
if (!run) {
return;//如果开关关闭,那就直接不执行下边的代码
}
run = false;//持续触发的话 run一直是false 就停在上边的判断那里 return
setTimeout(() => {
func.apply(null, arguments);
run = true;
}, delay)
}
}
box.onmousemove = throttle(function (e) {
box.innerHTML = `${e.clientX}, ${e.clientY}`
}, 1000)
Ps:箭头函数中没有this和arguments,this和arguments会向上一级作用域查找。
十三:静态资源优化方案.
(1).配置超长时间的本地缓存-节省宽带,提高性能。
(2).采用内容摘要作为缓存更新依据-精确的缓存控制。
(3).静态资源cdn部署-优化网络请求。
(4).资源发布路径实现非覆盖式发布-平滑升级。
十四:为什么使用cdn?
为了追求速度。因为浏览器缓存只是为了二次访问的速度,对于首次访问的加速,需要从网络层面进行优化,最常见的是cdn(内容分发网络)加速。通过将静态资源缓存到离用户很近的相同网络运营商的CDN节点上,不但能提示用户的访问速度,还能节省服务器的带宽消耗,降低负载。
十五: css优化?
(1)内容和样式分离。
(2)css压缩,减少体积。
(3)css可缓存、重用,维护成本降低。
(4)不使用@import。
(5)避免使用多层的选择器,层级越少越好。
(6)精简页面的样式文件,利用css继承减少代码量。
(7)书写顺序,按照位置>大小>文字系列>背景>其他。
十六:敏捷开发中的mvp。
mvp(Minimum viable product):最小化可行产品。
mvp是一个过程,在此阶段的主要目标是学习。在快的前提下,研发出可体验的/可使用的/令人喜爱的/能快速反馈的,用户真实体验,要抓住核心产品流程。
最小可行产品是:知道'方法'验证'方向'。
敏捷开发是:知道'方向'验证'方法'。
十七:模块和组件的区别?
模块具有可拆分性,模块由多个组件或者多个小模块构成,模块一般与业务相关联。
组件在功能上还是业务上都无法继续拆分,组件是构成业务模块或业务功能的基本单位。
模块化解决的问题:
1.解决由于模块边界定义不清而导致的耦合问题。
2.统一规定模块之间通信方式,去除过分使用EventBus而臃肿的event包。
3.隔离各个模块代码,利于并行开发测试。
4.可单独编译打包某一个模块,提升开发效率。
5.模块实现可复用,快速集成。
6.开发时,可以进行单业务编译,编码全量编译时过长。
模块化的技术难点:
1.隔离模块边界。模块与模块之间不允许同时直接产生依赖关系。
隔离的规则:
业务之间是否强关系?强关联的应该合并。
共用的功能是否可组件化?可组件化应该拆分。
业务是否复杂?复杂应该拆分。
空壳模块能否与其他空壳合并。
2.模块间跳转。使用router。
3.模块间通信。同一模块之间使用EventBus。不同模块之间使用协议通信。
十八:重构原因:
1.项目代码结构混乱,代码风格不统一,导致新手上手很慢。
2.不稳定。
3.有性能瓶颈。
4.不能满足新需求。
5.有大量重复代码,改动一个地方会牵连很多其他地方。
重构目标:
1.改进软件设计。
2.简化代码,让代码更容易阅读理解,方便后期维护拓展。
3.统一规范代码风格。
4.满足新需求。
5.发现并修改bug。
6.提高用户体验,性能优化。
7.使用面向对象思想。
重构内容:
1.熟悉项目。
2.解耦。拆分大文件,划分模块。比如是公用组件还是该页面的业务组件。
3.提取公用组件、公用样式。
4.精简代码。
5.封装请求拦截。
十九:自适应方案核心: 阿里可伸缩布局方案 lib-flexible
postcss-pxtorem是PostCSS的插件,用于将像素单元生成rem单位,在vue项目中使用pxtorem需要配置plugins的postcss-pxtorem的rootValue。
二十:kafka:是一个分布式发布-订阅模式的消息服务工具,依赖于zookeeper进行工作。数据的发送者以某种方式对消息进行分类,接收者订阅他们,以便接受特定类型的消息。发布与订阅系统有一个broker,也就是发布消息的中心点。用户分为生产者和消费者。
生产者创建消息:被称为发布者或写入者。生产者在默认的情况下把消息均衡的发布到主题的所有分区上,而并不关心特定消息会被写入到哪个分区。
消费者读取消息:被称为订阅者或读者。消费者订阅一个或多个主题,并按照消息生成的顺序来读取他们。消费者通过检查消息的偏移量来判断是否读过消息。
kafka特点:
1.按照topic对消息进行分类。
2.发送消息者为生产者。
3.订阅消息者为消费者。
4.一个或多个server组成的集群来进行,每一个server都称为一个broker。
kafka优势:
1.高吞吐量、低延迟。
2.可扩展性。
3.持久性、可靠性。
4.容错性。
5.高并发。
kafka适合的应用场景:
1.日志收集。一个公司可以用kafka收集各种服务的Log,通过kafka以统一接口服务的方式开放给各种consumer。
2.消息系统:解耦生产者和消费者、缓存消息等。
3.用户活动跟踪:kafka经常被用来记录web用户或者app用户的各种活动,如浏览网页、搜索、点击等活动,这些信息被各个服务器发布到kafka的topic中,
然后消费者通过订阅这些topic来做实时的监控分析,也可以保存到数据库。
4.运营指标:kafka用来记录运营监控数据。包括收集各种分布式应用的数据,生产各种操作的集中反馈,比如报警和报告。
5.流式处理。