cookie 是存储在浏览器上的一小段数据,用来记录某些当页面关闭或者刷新后仍然需要记录的信息。
用户在输入用户名密码提交给服务端,服务端验证通过后会创建一个 session 用于记录用户的相关信息,这个 session 可保存在服务器内存中,也可保存在数据库中。
localStorage HTML5 本地存储 web storage 特性的 API 之一,用于将大量数据(最大 5M)保存在浏览器中,保存后数据永远存在不会失效过期,除非用 JS 手动清除。
// 设置
document.cookie = 'age=16' // 每次只能设置一对cookie
// 获取
document.cookie // 获取全部cookie值,获取特定用循环
// 删除
document.cookie = 'name=xiaoming; max-age=-1000' // 设置一个当前之前的时间即可
// 设置过期时间
var name = 'one_name'
var value = '123'
var exp = new Date()
exp.setTime(exp.getTime() + 60 * 2000) // 过期时间 2分钟
document.cookie = name + "=" + escape(value) + ";expires=" + exp.toGMTString()
console.log(name + "=" + escape(value) + ";expires=" + exp.toGMTString())
// 如果不在浏览器中设置过期时间,cookie 被保存在内存中,生命周期随浏览器的关闭而结束,
// 这种 cookie 简称会话 cookie。
// 如果在浏览器中设置了 cookie 的过期时间,cookie 被保存在硬盘中,
// 关闭浏览器后,cookie 数据仍然存在,直到过期时间结束才消失。
- cookie:是服务器发给浏览器保存的(字符串)数据,一般用来记录用户信息方便服务端确认用户身份
- localStorage、sessionStorage:本地存储,可以保存一些不太重要的数据,例如当前用户坐标,购物车信息等
- cookie:4k
- localStorage, sessionStorage:5M
- cookie:关闭浏览器失效(默认)
- localStorage:永久,除非js手动删和清除浏览器缓存
- sessionStorage:页面不关闭就不失效,包括重新加载或恢复页面也不失效。但在新标签或窗口打开一个页面,则会重新生成
都是用来确认用户身份的,区别在于 cookie 保存在客户端,session 保存在服务端。
另外,session 是基于 cookie 的。服务器端在生成 session 后,会让客户端的 cookie 代为保存 sessionID 。
阅读:
- 一文带你看懂cookie,面试前端不用愁
- 聊一聊cookie
- Cookie禁用了,Session还能用吗?
- session,cookie,sessionStorage,localStorage的区别及应用场景
所有人都知道,localStorage和sessionStorage的最大区别是生命周期,一个永久,一个仅针对一个会话期间有效。那么,到底什么是一个会话?多个标签页之间的数据是否会共享呢?
我们对会话session的认识一般都是从后台的session开始的,比如Java的session,它是基于往cookie写入一个JSESSIONID来实现的,所以,只要你不是打开一个隐身窗口,无论你开多少个标签页,不同标签页之间都会被认为是一个session,你在这个标签页登录了,新开一个标签输入地址,仍然是登录状态。
但是直到今天才发现,HTML5中的这个sessionStorage和传统后台的session并不完全是同一个东西,主要是在多个标签页数据是否会共享的问题上的不同。
误区:之前一直以为,同一个窗口,只要会话还没有过期,不同标签页之间,相同域名下的sessionStorage是一样的。
正确答案:刷新当前页面,或者通过location.href、window.open、或者通过带target="_blank"的a标签打开新标签,之前的sessionStorage还在,但是如果你是主动打开一个新窗口或者新标签,对不起,打开F12你会发现,sessionStorage空空如也。
也就是说,sessionStorage的session仅限当前标签页或者当前标签页打开的新标签页,通过其它方式新开的窗口或标签不认为是同一个session。
大家可以亲自测试一下,手动打开的新标签和点A标签打开的新标签效果完全不一样。
今天又碰到有关sessionStorage的一个问题,比如当我通过A标签打开新的窗口时,在新窗口删除同样的数据,旧窗口的却还在。
经过测试发现:
通过带target="_blank"的A标签、window.open等方式打开新窗口时,会把旧窗口(或标签)的sessionStorage数据带过去,但从此之后,新窗口(或标签)的sessionStorage的增删改和旧窗口已经没有关系了,如果只是在当前标签内跳转新页面(或者刷新),数据还会保留(前提当然是同域)。
总之,在处理sessionStorage时,只要打开新窗口就要特别注意了,新旧窗口数据不会互相同步。
1. websocket 通讯
全双工(full-duplex)通信自然可以实现多个标签页之间的通信。
2. 定时器 setInterval+cookie
在页面 A 设置一个使用 setInterval 定时器不断刷新,检查 Cookies 的值是否发生变化,如果变化就进行刷新的操作。
3. 使用 localStorage
localStorage 是浏览器多个标签共用的存储空间,所以可以用来实现多标签之间的通信(ps:session 是会话级的存储空间,每个标签页都是单独的)。
直接在 window 对象上添加监听即可:
window.onstorage = (e) => {console.log(e)}
// 或者这样
window.addEventListener("storage", (e) => console.log(e))
在用户没有与因特网连接时,可以正常访问站点或应用,在用户与因特网连接时,更新用户机器上的缓存文件。 原理:HTML5的离线存储是基于一个新建的 .appcache 文件的缓存机制(不是存储技术),通过这个文件上的解析清单离线存储资源,这些资源就会像cookie一样被存储了下来。之后当网络在处于离线状态下时,浏览器会通过被离线存储的数据进行页面展示。
如何使用:
- 页面头部像下面一样加入一个manifest的属性
- 在 cache.manifest 文件的编写离线存储的资源
- 在离线状态时,操作 window.applicationCache 进行需求实现。
详细的使用请参考:
在线的情况下:
浏览器发现 html 头部有 manifest 属性,它会请求 manifest 文件,如果是第一次访问 app ,那么浏览器就会根据 manifest 文件的内容下载相应的资源并且进行离线存储。如果已经访问过 app 并且资源已经离线存储了,那么浏览器就会使用离线的资源加载页面,然后浏览器会对比新的 manifest 文件与旧的 manifest 文件,如果文件没有发生改变,就不做任何操作,如果文件改变了,那么就会重新下载文件中的资源并进行离线存储。
离线的情况下:
浏览器就直接使用离线存储的资源。
- 将购物车信息存在 localStorage
- 从 localStorage 中获取
- 用户禁用 cookie 时无法使用
- IE 浏览器不支持 Promise
- babel-polyfill → webpack.config.js 的 entry 中设置 ['babel-polyfill', './src/main.js']
- 各浏览器之间默认样式的差异
- normalize.css
- 与 reset 区别 → normalize.css 消除各浏览器之间默认样式的差异、保留有用的默认样式;而 reset 会清除所有的默认样式,过于暴力,例如会让 h 标题标签不再默认加粗,ul li 前面默认的小圆点也没了)
- normalize.css
- html5 某些新增标签不被识别
- html5shiv.js - 解决 ie9 以下对 html5 某些新增标签不识别的问题(e.g. video标签不识别不显示)
- 用法:
[if lt IE 9]><script> src="http://html5shim.googlecode.com/svn/trunk/html5.js"</script><![endif]
- 用法:
- 通过 document.createElement 方法产生的标签, 可以利用这一特性让这些浏览器支持HTML5新标签,浏览器支持新标签后,还需要添加标签默认的样式。
- html5shiv.js - 解决 ie9 以下对 html5 某些新增标签不识别的问题(e.g. video标签不识别不显示)
- CSS3 媒体查询失效
- respond.js - 能解决 ie9 以下不支持媒体查询问题
- 自动添加浏览器前缀
- posscss-loader+autoprefixer
- ie6 不支持 min-height/width
- 添加额外的
_min-height
ie6 识别
- 添加额外的
- 常见hack(针对特定ie版本的样式控制)
- _color - ie6 识别
- *color - ie6/7 识别
- color: red\9; ie8及以下识别
- ie条件注释写法:(lt 小于 | gt 大于 | lte 小于等于 | gte 大于等于 | ! 不等于)
- 移动端点透问题
- ios滚动卡顿
- 使用 better-scroll 插件
- ios 顶部输入框 fixed 布局失效(当键盘弹起时)❌
- 安卓 键盘遮挡输入框 ❌
原因:
fixed 的元素是相对整个页面固定位置的,你在屏幕上滑动只是在移动这个所谓的 viewport , 原来的网页还好好的在那,fixed 的内容也没有变过位置。
解决:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"/>
click 有 300ms 延迟,为了实现safari的双击事件的设计,浏览器要知道你是不是要双击操作。
参考阅读:H5与APP混合开发遇到的问题总结
polyfill 是“在旧版浏览器上复制标准 API 的 JavaScript 补充”,可以动态地加载 JavaScript 代码或库,在不支持这些标准 API 的浏览器中模拟它们。
例如,geolocation(地理位置)polyfill 可以在 navigator 对象上添加全局的 geolocation 对象,还能添加 getCurrentPosition 函数以及“坐标”回调对象, 所有这些都是 W3C 地理位置 API 定义的对象和函数。
因为 polyfill 模拟标准 API,所以能够以一种面向所有浏览器未来的方式针对这些 API 进行开发, 一旦对这些 API 的支持变成绝对大多数,则可以方便地去掉 polyfill,无需做任何额外工作。
比如: html5shiv、Geolocation、Placeholder
触发事件的元素被认为是目标(target)。而在 IE 中,目标包含在 event 对象的 srcElement 属性
如果按键代表一个字符(shift、ctrl、alt除外),IE 的 keyCode 会返回字符代码(Unicode),DOM 中按键的代码和字符是分离的,要获取字符代码,需要使用 charCode 属性
IE 中阻止某个事件的默认行为,必须将 returnValue 属性设置为 false,Mozilla 中,需要调用 preventDefault() 方法
IE 中阻止事件进一步冒泡,需要设置 cancelBubble 为 true,Mozzilla 中,需要调用 stopPropagation()
WebSocket、SharedWorker;
也可以调用 localStorage 、cookies 等本地存储方式;
localStorage 另一个浏览上下文里被添加、修改或删除时,它都会触发一个事件, 我们通过监听事件,控制它的值来进行页面信息通信;
注意:Safari 在无痕模式下设置localStorage 值时会抛出 QuotaExceededError 的异常;
Adobe Flash Socket 、 ActiveX HTMLFile (IE) 、 基于 multipart 编码发送 XHR 、 基于长轮询的 XHR
- DNS 查询
- 建立 TCP 连接(三次握手)
- 发送 HTTP 请求
- 服务端web服务器对请求做处理(监听80端口 路由 渲染HTML模板 生成响应)
- 发送 HTTP 响应
- 关闭 TCP 连接(四次挥手)
- 浏览器解析HTML,CSS,图片,JS
- 处理 HTML 标记并构建 DOM 树
- 处理 CSS 标记并构建 CSS 规则树
- 将 DOM树 与 CSS规则树 合并成一个渲染树。
- 根据渲染树来布局,以计算每个节点的几何信息。
- 将各个节点绘制到屏幕上
这五个步骤并不一定一次性顺序完成。如果 DOM 或 CSSOM 被修改,以上过程需要重复执行,这样才能计算出哪些像素需要在屏幕上进行重新渲染。实际页面中,CSS 与 JavaScript 往往会多次修改 DOM 和 CSSOM
阅读更多:
style 标签放在 body 后,会导致当加载到此样式时,页面将停止之前的渲染。此样式表被解析后,将重新渲染页面,也就出现了短暂的花屏现象。
所以不要写在 body 后,要把样式放在 head 中。
- 相同点:最终都是走的本地缓存
- 不同点:强缓存不发请求,直接读本地缓存。协商缓存发请求到服务器
- 1)浏览器在加载资源时,根据请求头的
expires
和cache-control
判断是否命中强缓存,是则直接从缓存读取资源,不会发请求到服务器。 - 2)如果没有命中强缓存,浏览器一定会发送一个请求到服务器,通过
last-modified
和Etag
验证资源是否命中协商缓存,如果命中,服务器会将这个请求返回,但是不会返回这个资源的数据,依然是从缓存中读取资源 - 3)如果前面两者都没有命中,直接从服务器加载资源
- 用 HTML 标签设置 HTTP 头信息:
<meta http-equiv="Pragma" content="no-cache">
header("Cache-Control: no-cache, must-revalidate")
<meta http-equiv="Cache-Control" content="no-cache">
<meta http-equiv="Expires" content="0">
说明:HTTP 头信息 Expires 和 Cache-Control 为应用程序服务器提供了一个控制浏览器和代理服务器上缓存的机制。
HTTP 头信息 Expires 告诉代理服务器它的缓存页面何时将过期。
HTTP1.1 规范中新定义的头信息 Cache-Control 可以通知浏览器不缓存任何页面。当点击后退按钮时,浏览器重新访问服务器已获取页面。
如下是使用 Cache-Control 的基本方法:
1)no-cache:强制缓存从服务器上获取新的页面;
2)no-store:在任何环境下缓存不保存任何页面。
HTTP1.0 规范中的 Pragma: no-cache等同于 HTTP1.1 规范中的 Cache-Control: no-cache,同样可以包含在头信息中。
- 在需要打开的 url 后面增加一个随机的参数: 增加参数前:url=test/test.jsp 增加参数后:url=test/test.jsp?ranparam=random()
都是用的本地系统时间,但
- expires 存的是个服务端绝对时间,修改客户端系统时间会有影响
- cache-control 是相对时间,即使客户端时间发生改变,相对时间也不会随之改变。例如设置 max-age = 10s,那么在 10s 以内,使用浏览器缓存的资源
- cache-control 的优先级高于 expires
- 语义:GET 用来读数据,POST 用来写数据
- 参数:GET 放在 url 里,POST 放消息体里
- 大小:GET 长度有限制,一般 1024 个字符。POST 4~10Mb 限制
- 缓存:GET 请求可以被浏览器缓存,POST 不能
一个不发请求,一个发请求。超过缓存时间,只要 if-None-Match 和服务器端 etag 相同,仍然缓存。并且 Etag 比 cache-control 的优先级更高。
是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。
- 一种是建立一个信息安全通道,来保证数据传输的安全
- 另一种就是确认网站的真实性。
- https 协议需要到 ca 申请证书,有免费付费可选
- http是明文传输,https 则是具有安全性的 ssl 加密传输协议。
- 非对称加密
- 性能问题:https 做了加密就意味着客户端服务端也需要附带解密步骤,相比来说,在通讯快捷上,性能有所不如 http 。
不要去硬记。 你只要想:既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密;同理,既然是签名,那肯定是不希望有人冒充我发消息,只有我才能发布这个签名,所以可得出私钥负责签名,公钥负责验证。
参考:
- 客户端使用https的url访问web服务器,要求与服务器建立ssl连接
- web服务器收到客户端请求后, 会将网站的证书(包含公钥)传送一份给客户端
- 客户端收到网站证书后会检查证书的颁发机构以及过期时间, 如果没有问题就随机产生一个秘钥
- 客户端利用公钥将会话秘钥加密, 并传送给服务端, 服务端利用自己的私钥解密出会话秘钥
- 之后服务器与客户端使用秘钥加密传输
参考来源:
阅读更多:
- 基于HTTPS的
- 多路复用
- 服务端推送
阅读更多:多路复用
HTTP2采用二进制格式传输,取代了HTTP1.x的文本格式,二进制格式解析更高效。
多路复用代替了HTTP1.x的序列和阻塞机制,所有的相同域名请求都通过同一个TCP连接并发完成。在HTTP1.x中,并发多个请求需要多个TCP连接,浏览器为了控制资源会有6-8个TCP连接都限制。
HTTP2中:
- 同域名下所有通信都在单个连接上完成,消除了因多个 TCP 连接而带来的延时和内存消耗。
- 单个连接上可以并行交错的请求和响应,之间互不干扰。
阅读更多:
- 压缩
- html,css,js【html-webpack/optimize-css-assets/webpack-parallel-uglify】-plugin
- 图片:image-webpack-loader,雪碧图,iconfont图标字体
- 合并
- 减少http请求,每个http请求都带来慢启动,三次握手,连接建立,所以资源合并由为重要
- 服务端启用 gzip(压缩率80%)
- 浏览器请求 header 设置 accept-encoding: gzip
- 服务器响应 header 返回 content-encoding: gzip【apache的 httpd.conf】
原理:html 在转 DOM 时,节点引用 css/img 不影响继续转化,但 js 会阻塞,因为 js 有可能修改 dom 树
- css 放 head
- js 尽量不放 head,如果放则 js 内嵌,且在所有css前面 | 对于会阻塞后续内容的外部 js ,用 defer
- 首屏优化
- 懒加载:列表滚动图片懒加载
- 按需加载 webpack codespliting
- 使用cdn加速:把静态资源(能被浏览器缓存的js/css)分发到离用户最近节点就近获取,提高响应速度和成功率
- http协议缓存:强缓存/协商缓存
- 使用浏览器缓存来减少请求数量
- css,js 加 MD5 后缀
- 本地存储 localStorage (地理位置,购物车)
- app cache ❌
- service worker ❌
- 减少重绘和重排
- 集中改变样式(cssText,类名切换)
- 批量修改DOM(display:none,createDocumentFragment)
- 读写分离(尽量不要一行代码又读又写 div.style.left = div.offsetLeft + 1 + 'px'; <=重复两次就是两次重排,先存起来就只会导致一次重排)
- 动画
- css3动画
- webkit-transform: translateZ(0); / will-change: transform;
- GPU渲染,浏览器生成DOM元素快照,在GPU的层上缓存起来做单独做动画
- webkit-transform: translateZ(0); / will-change: transform;
- js动画
- 使用 requestAnimationFrame 提升流畅度(确保js尽早在每一帧开始时执行)
- css3动画
- 列表滚动重用(类似ios cell复用)❌
- 使用SSR(server side rendering)后端渲染,数据直接输出到HTML ❌
需要引入jquery
兼容所有浏览器
$(document).ready(function() {
alert("加载完成!");
});
async属性是HTML5新增属性,需要Chrome、FireFox、IE9+浏览器支持
async属性规定一旦脚本可用,则会异步执行
async属性仅适用于外部脚本
此方法不能保证脚本按顺序执行
<script type="text/javascript" src="xxx.js" async="async"></script>
defer属性规定是否对脚本执行进行延迟,直到页面加载为止
如果脚本不会改变文档的内容,可将defer属性加入到``标签中,以便加快处理文档的速度
兼容所有浏览器
此方法可以确保所有设置了defer属性的脚本按顺序执行
兼容所有浏览器
(function(){
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = "http://code.jquery.com/jquery-1.7.2.min.js";
var tmp = document.getElementsByTagName('script')[0];
tmp.parentNode.insertBefore(script, tmp);
})();
功能检测、userAgent特征检测
比如:navigator.userAgent
//"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36"
function isAndroid() {
return /Android/.test(navigator.userAgent);
}
function isiPhone() {
return /iPhone/.test(navigator.userAgent);
}
function isiPad() {
return /iPad/.test(navigator.userAgent);
}
function isiOS() {
return /(iPhone)|(iPad)/i.test(navigator.userAgent);
}
主要分成两部分:
渲染引擎(Layout engineer 或Rendering Engine)和JS引擎。
- 渲染引擎:负责取得网页的内容(HTML、XML、图像等等)、整理讯息(例如加入CSS等),以及计算网页的显示方式,然后会输出至显示器或打印机。浏览器的内核的不同对于网页的语法解释会有不同,所以渲染的效果也不相同。所有网页浏览器、电子邮件客户端以及其它需要编辑、显示网络内容的应用程序都需要内核。
- JS引擎则:解析和执行javascript来实现网页的动态效果。 最开始渲染引擎和JS引擎并没有区分的很明确,后来JS引擎越来越独立,内核就倾向于只指渲染引擎。
详细文章:浏览器内核的解析和对比
形象记忆:https://http.cat/
- 200 服务器成功返回请求
- 301 永久重定向,浏览器会记住 | 302 临时重定向 | 304 请求页面未修改
- 400 请求错误,服务器不理解 | 401 请求未授权 | 403 服务器拒绝请求 | 404 资源不存在 | 405 方法禁用
- 500 服务器内部错误 | 503 服务暂时不可用(超载or停机维护)
- 通过 visibilityState 的值检测页面当前是否可见,以及打开网页的时间等;
- 在页面被切换到其他后台进程的时候,自动暂停音乐或视频的播放;
区分用户是计算机还是人的公共全自动程序。可以防止恶意破解密码、刷票、论坛灌水; 有效防止黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试。
多数显示器默认频率是60Hz,即1秒刷新60次,所以理论上最小间隔为1/60*1000ms = 16.7ms
localStorage
- onhashchange
- window.history.pushState(添加新的历史记录)/replaceState(state,title, url)【改掉当前历史记录】
- 配合 onpopstate 事件来监听历史记录的改变
实现了客户端与服务端之间的全双工通信,当服务端数据变化时,可以第一时间通知到客户端。
- http 只能由客户端发起,而 webSocket 是双向的
- webSocket 传输的数据包相对于 http 而言很小,很适合移动端使用
- 没有同源限制,可以跨域共享资源
是面向连接的协议,也就是说,在收发数据前,必须和对方建立可靠的连接。 一个TCP连接必须要经过三次“对话”才能建立起来
- 第一次握手:主机 A 通过向主机 B 发送一个含有同步序列号的标志位的数据段给主机 B ,向主机 B 请求建立连接,通过这个数据段, 主机 A 告诉主机 B 两件事:我想要和你通信;你可以用哪个序列号作为起始数据段来回应我。
- 第二次握手:主机 B 收到主机 A 的请求后,用一个带有确认应答(ACK)和同步序列号(SYN)标志位的数据段响应主机 A,也告诉主机 A 两件事:我已经收到你的请求了,你可以传输数据了;你要用那个序列号作为起始数据段来回应我
- 第三次握手:主机A收到这个数据段后,再发送一个确认应答,确认已收到主机B 的数据段:"我已收到回复,我现在要开始传输实际数据了,这样3次握手就完成了,主机 A 和主机B 就可以传输数据了。
- 第一次: 当主机A完成数据传输后,将控制位FIN置1,提出停止TCP连接的请求 ;
- 第二次: 主机 B 收到 FIN 后对其作出响应,确认这一方向上的 TCP 连接将关闭,将ACK置1;
- 第三次: 由 B 端再提出反方向的关闭请求,将 FIN 置 1 ;
- 第四次: 主机 A 对主机 B 的请求进行确认,将 ACK 置 1 ,双方向的关闭结束。
UDP 是一个非连接的协议,传输数据之前源端和终端不建立连接, 当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。
1、TCP 面向连接;UDP 不面向连接;
2、TCP 传输可靠(三次握手),UDP 则不可靠,不保证正确性(UDP 传送数据前并不与对方建立连接,对接收到的数据也不发送确认信号,发送端不知道数据是否会正确接收,当然也不用重发);
3、UDP 开销小,传输快;
- TCP:效率要求相对低,但对准确性要求相对高的场景(文件传输,邮件接收,远程登录)
- UDP:效率要求相对高,但对准确性要求相对低的场景(在线视频,语音电话)
参考:OSI七层协议大白话解读
Content Delivery Network,简称CDN,翻译成中文是内容分发网络。
CDN是通过在网络上的各个地方放置一定数量的节点服务器,构成在现有的互联网基础之上的一层智能虚拟网络,这层网络的主要功能是将信息(源站内容)分发至靠近用户的各个节点服务器上,让用户可以就近获取所需信息。
通过CDN,可以有效降低源站的访问压力,减轻骨干网络的拥塞,提升用户的访问速度,从而提升用户体验。还可在一定程度上保障源站的安全。
CDN 的用途可以说很窄,也可以说很广。说窄是因为CDN只是基于互联网之上的一种服务,只是给网络/网站加速的;说广是因为几乎所有的互联网业务(如网页、电商、APP、游戏、下载、影视点播、直播等等)都需要用到 CDN ,而如今互联网又无处不在。
来源:https://www.zhihu.com/question/282510029/answer/427307826