Coder Social home page Coder Social logo

aaronphy.github.io's People

Stargazers

 avatar  avatar  avatar

Watchers

 avatar

aaronphy.github.io's Issues

useful webpack plugins

case-sensitive-paths-webpack-plugin

  • This Webpack plugin enforces the entire path of all required modules match the exact case of the actual path on disk. Using this plugin helps alleviate cases where developers working on OSX, which does not follow strict path case sensitivity, will cause conflicts with other developers or build boxes running other operating systems which require correctly cased paths.

friendly-errors-webpack-plugin

  • This Webpack plugin recognizes certain classes of webpack errors and cleans, aggregates and prioritizes them to provide a better Developer Experience.

terser-webpack-plugin

  • This plugin uses terser to minify your JavaScript.

千岛湖游记

老婆想吃千岛湖鱼头,于是决定这次清明节去千岛湖,其实去年团队outing去过一次,行程安排的不是很好,很多优质的景点没有玩到,所以决定再去一次,列了几个点一定要去:

景点:

  • 芹川古镇
  • 黄山尖
  • 千岛湖湖心

吃:

  • 清水鱼坊
  • 几荷(秀水广场)

等待我的美食与照片吧

更新

脚崴了,居然骨折我擦····,千岛湖之游估计只能到我脚好了,估计4月下旬了~

Recent Read 2021.01

linux下 快捷建

Ctrl+b 或左箭bai头du键 左移一个字符(移zhi至前一个字符)
Ctrl+f 或右dao箭头键 右移一个字符(移至后一个字符)
Ctrl+a 移至行首
Ctrl+e 移至行尾
Esc b 左移一个单词
Esc f 右移一个单词
Del 删除光标所在处的字符
Ctrl+d 删除光标所在处的字符
BACKSPACE或Ctrl+h 删除光标左边的字符
Ctrl+k 删除至行尾

DOM自省

页面内容的CRUD

基操

  • 获取元素可以用哪些方法?documeng.querySelector等等
  • 修改获取到的元素内容?innerText 和 innerHTML等等
  • 如何创建元素?createElement
  • 如何添加元素?appendChild,insertBefore
  • 如何删除元素?removeChild

进阶

  • 一次性插入3000000个节点,如何实现,如何优化?DocumentFragment,RAF
  • 写一个RAF?
    (function() {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] 
                                   || window[vendors[x]+'CancelRequestAnimationFrame'];
    }
 
    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function() { callback(currTime + timeToCall); }, 
              timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };
 
    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());

页面的事件流

javascript 正则温习

正则就是匹配模式:用于匹配字符串中字符组合的模式

“要么匹配字符,要么匹配位置”--至理名言

JS中使用正则表达式

构建正则表达式

  • 字面量构建
let reg = /abc/;
  • 构造函数
let reg = new RegExp('abc')

使用正则表达式

正则表达式也是对象: RegExpexec 以及 test方法。

当然还有就是字符串的一些方法也可以使用正则表达式比如:match,matchAll,replace,search以及split

方法 描述
exec 一个在字符串中执行查找匹配的RegExp方法,它返回一个数组(未匹配到则返回 null)
test 一个在字符串中测试是否匹配的RegExp方法,它返回 true 或 false。
match 一个在字符串中执行查找匹配的String方法,它返回一个数组,在未匹配到时会返回 null。
matchAll 一个在字符串中执行查找所有匹配的String方法,它返回一个迭代器(iterator)。
search 一个在字符串中测试匹配的String方法,它返回匹配到的位置索引,或者在失败时返回-1。
replace 一个在字符串中执行查找匹配的String方法,并且使用替换字符串替换掉匹配到的子字符串。
split 一个使用正则表达式或者一个固定字符串分隔一个字符串,并将分隔后的子字符串存储到数组中的 String 方法。

匹配字符

模糊匹配

匹配字符串长度不固定-横向模糊匹配

主要是用量词来实现:

 /ab{2,5}c/  

{m,n} :连续出现,最少m次,最多n次

量词
量词 含义
{m,} 至少出现m次
{m} 出现m次
? 有或者没有,等价于{0,1}
+ 至少出现1次,等价于{1,}
* 出现任意次,等价于{0,}

匹配到某个位置,这个位置的字符有多种可能- 纵向模糊匹配

主要是使用字符组来实现:

/a[134]b/

[xyz] : x,y,z中任何一个

字符组

需要注意的虽然叫字符组,但是匹配的只是一个字符

  • 表示范围,用连字符 - 来表示,比如[123456] = [1-6]
  • 排除 用 ^ 来表示 ,比如 [^abc]
  • 常用简写字符组
字符组 含义
\d [0-9] 表示一位数字
\D [^0-9]表示除数字意外的任意字符
\w [0-9a-zA-Z_]表示数组字母下划线
\W [^0-9a-zA-Z_]表示非数字字母下划线
\s [\t\v\b\r\f]表示空白符,包括空格,制表,换行,回车,换页
\S [^\t\v\b\r\f]表示非空白符
. [^\n\r\u2028\u2029]通配符,但换行,回车,行分隔,段分隔除外
贪婪和惰性匹配

30w-40w车推荐

轿车推荐 C级

街车(保值率高)

2021 宝马325i M

有钱可以上黑曜版本,的确很好看

雷克萨斯 ES200

预算再高点,可以上ES300H, 混动的很省油,ES200h 好像没有了

奥迪A4L

乞丐版本估计没有货,没必要上quattro

稍微小众 (撞车几率小)

林肯MKZ

有混动版本,贯穿式车尾,乳白色很不错,稍微显沉稳点

凯迪拉克ct5

优惠很多,可以看看,油耗惊人

沃尔沃S60

新能源版本可以考虑下

SUV 不区分街车 和 小众了,**人都喜欢SUV

林肯航海家

有款蓝色很好看,坐着炒鸡舒服,隔音好,视野也不错

奔驰GLC

内饰无敌,隔音不错

奥迪Q5L

后排空间没有想象大,不过sportback蓝色很好看,操控很好

沃尔沃XC60

独一无二的存在,操控以及安全性,空间也很大

坦克300

太帅了,非承载车身,开过,很不错,国产之光

汉兰达

丰田神车之一

英菲尼迪QX50

银色真的好看

TS技巧集合

高阶函数+装饰器

const withLoading = <T extends {}>(Component:React.ComponentType<T>)=>{
    const Loading:React.FC<T = (props:T)=>{
        const [loading,setLoading] = React.useState(false)
        return (
            <>
                {loading? <div>loading...</div>
                : <Component {...props} visible={(e)=>setLoading(e)}>
                }
            <>
        )
    }
} 

函数组件使用
const XXXHOC = withLoading(XXX)
类组件使用

const DecoratorWithLoading:<T extends {}>(Component:ComponentType<T>) => any = withLoading;
@DecoratorWithLoading
class XXX extends React.Component{}

元组定义类型

const arr = ['a','b','c'];

const tuple = (...args:T)=>args;

const tupleArr = tuple('a','b','c');

type Type = {
    [k in (typeof tupleArr)[number]]:string
}

type Type = {a:string,b:string,c:string}

前端性能指标

老指标

web 性能.png

原来的各种指标, 很晦涩哦~

名称 含义
FP First Paint ,第一个像素被绘制在屏幕上的时刻
FCP First Contentful Paint ,第一个内容被绘制在屏幕上的时刻
FMP First Meaningful Paint ,主要内容被绘制在屏幕上的时刻
SI Speed Index 页面可见内容填充速度
LCP Largest Contentful Paint 最大元素被绘制的时刻
FCI First CPU Idle 第一次CPU空闲可处理IO时刻
TTI Time To Interactive 可稳定交互的时刻
FID First Input Delay 代表用户第一次交互处理消耗时间

根据RAIL模型来收集对应的指标:

  • 首页白屏时间:FP/FCP
  • 是否有用:FMP
  • 是否可用:TTI
  • 是否流畅:Long Task

FP/FCP计算

const observer = new PerformanceObserver((list) => {
    for (const entry of list.getEntries()) {
      // `name` will be either 'first-paint' or 'first-contentful-paint'.
      const metricName = entry.name;
      const time = Math.round(entry.startTime + entry.duration);
      //发送数据到后台
      request.post({
        eventCategory:'Performance Metrics',
        eventAction: metricName,
        eventValue: time,
        nonInteraction: true,
      })
    }
  });
  observer.observe({entryTypes: ['paint']});

FMP计算

更多的是标记元素的方法来去监听

TTI 计算

import ttiPolyfill from 'tti-polyfill';

ttiPolyfill.getFirstConsistentlyInteractive().then((tti) => {
  request.post({
    eventCategory:'Performance Metrics',
    eventAction:'TTI',
    eventValue: tti,
    nonInteraction: true,
  });
});

Long Tasks

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    request.post({
      eventCategory:'Performance Metrics',
      eventAction: 'longtask',
      eventValue:Math.round(entry.startTime + entry.duration),
      eventLabel:JSON.stringify(entry.attribution),
    });
  }
});

observer.observe({entryTypes: ['longtask']});

新指标

截屏2021-05-05 下午4.12.16.png

最大内容渲染 LCP

由于LCP 关心的是文本块和图像,因此寻找的元素节点限定为:

  • img
  • svg
  • video
  • url背景图
  • 包含text的块级元素

首次输入延迟 FID

累积布局偏移 CLS

很久没有温习的Webpack

webpack的工作流程是基于事件机制,而它的核心就是tapable 这个事件生命周期扩展类。

计算机网络复习-HTTP

HTTP

HyperText Transfer Protocol 超文本传输协议,基于TCP协议的应用层传输协议,在客户端与服务端进行数据传输的一种协议规则

特点

  • 支持客户端/服务端模式
  • 简单快速:客户端向服务端请求数据时,只需要发送请求方法和路径
  • 灵活:允许传输任意类型的数据对象,用Content-Type来标记MIME Type
  • 无连接:并不是无连接,而是每次连接只处理一个请求,即请求/响应成对处理,服务器处理完客户的请求,并收到客户的应答后就断开连接,节省传输时间
  • 无状态:是指对于事务处理没有记忆,意味着如果处理需要前面的信息,则必须重传,但通过cookie以及session可以记录一些状态来弥补一些事务处理
http://host[":"port][/path]

HTTP 请求消息格式

http_rquest.png

请求行 -> 必须在第一行
请求头 -> 键值对
请求体 -> 具体根据请求方法以及请求头来确定

HTTP URI/URL

http使用统一资源标识符来建立连接和传输数据(Uniform Resource Identifiers)

HTTP 请求方法

基于 HTTP 1.1

方法 描述 特点
GET 用来请求访问已被URI识别的资源 请求参数追加在URL后面,没有请求体,参数长度因为客户端URL而有限制,比如ie /safari 为2kb,firefox/chrome为8kb, 一般Web服务器限制为8kb
POST 在Request-URI所标识的资源后附加新的数据 请求参数放在请求体,相对于GET较为安全,且数据大小没有限制,服务器一般为2GB
HEAD 和GET相似 服务端接收到HEAD请求只返回响应头,不返回响应内容,如果要查看某个页面的状态时,HEAD更高效,因为传输时间更节省
DELETE 用于删除某个资源
PUT 存储某个资源,与DELETE相反 与POST很相似,但PUT通常制定了资源的存放位置,而POST则没有,POST存放数据由服务器自己决定
TRACE 回显服务器收到的请求 主要用于测试或者诊断
OPTIONS 用于获取当前URL所支持的方法 若请求成功,会在HTTP头中包含一个名为"ALLOW"的头,值是所支持的方法
CONNECT 预留方法,能够将连接改为管道方式的代理服务器 通常用于SSL加密服务器的连接与非加密的HTTP代理服务器的通信
关于REST 架构

对HTTP协议本身的使用做了一些约束:

  • 面向资源,每个URI代表一个资源
  • 强调URL暴露资源时,不要在URI中出现动词
  • 合理利用HTTP状态码、请求方法
  • 强调无状态化,服务器不能存储来自某个客户请求中的信息

HTTP 请求头

字段名 描述 例子
Accept 客户端可以处理的响应类型(MIME类型) Accept:image/gif
Accept-Charset 客户端可处理的字符集 UTF-8
Accept-Encoding 客户端支持的数据压缩格式 Accept-Encoding: gzip, deflate, br
Accept-Langulage 客户端指定的语言类型 Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7
Authrization web认证信息
Connection 连接的管理,keep-live持久连接,close已关闭
Cache-Control 控制缓存行为 cache-control: no-cache
Content-Legnth 请求体的长度
Cookie 客户端cookie 客户端的信息通过这个带给服务端使用
Host 请求报头域主要用于指定被请求资源的 Internet 主机和端口号 比如www.baidu.com
If-Match 比较实体标记 Etag
If-Modified-Since 比较资源更新时间
If-None-Match 与If-Match相反比较
if-Range 资源未更新时发送实体Byte的范围请求
Referer 表示这个请求从哪儿URL跳过来的 常用于放盗链
Range 实体的字节范围请求
User-Agent 客户端浏览器与操作系统相关信息 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36

HTTP 请求体

当请求方式是POST/PUT的时候,请求体会有请求的参数

HTTP 响应报文格式

http_response.png

状态行
消息报头
响应正文

HTTP 响应状态码 以及 原因

常见状态码:

  • 200:OK 客户端请求成功
  • 400:Bad Request 客户端请求语法错误
  • 401:Unauthorized 请求未经授权,需要和WWW-Authenticate一起使用
  • 403:Forbidden 服务拒绝
  • 404:Not Found 请求资源不存在
  • 500:Internal Server Error 服务器发生不可预期错误
  • 503:Server Unavailable 当前服务器不能处理客户端请求

更多参考MDN

HTTP 响应头

字段名 描述 例子
Access-Control-Allow-Origin 一个返回的 HTTP 标头可能会具有 Access-Control-Allow-Origin ,Access-Control-Allow-Origin 指定一个来源,它告诉浏览器允许该来源进行资源访问
Server 服务器标头包含有关原始服务器用来处理请求的软件的信息。 Server: Apache/2.4.1 (Unix)
Set-Cookie Set-Cookie 用于服务器向客户端发送 sessionID。
Expires 数据过期时间
Last-Modified 资源的最后修改时间
Age 资源的创建时间
Location 客户端重定向至指定的URL
Date 普通报头域表示消息产生的日期和时间
Cache-Control 控制缓存行为

HTTP 版本

0.9

最早的0.9版本,1991年提出,目的是两个网络之间传输HTML内容,特点:

  • 请求只有请求行,没有请求头和请求体。静态页面不需要这些。
  • 服务器有不需要返回头信息,只需要返回请求数据即可。
  • 返回文件的内容是 ASCII 字节码来传输的,因为都是 HTML 文件,用 ASCII 字节码来传输也比较合适。

HTTP/1.0 构建可扩展性

1994年,支持多协议,多编码,特性:

  • HTTP/1.0 版本是一种无状态、无连接的应用层协议。
  • 浏览器与服务器每次请求都要建立连接,服务器处理完毕立刻断开连接。即浏览器与服务器之间只保持很短的连接时间。
  • 队头阻塞。HTTP/1.0规定下一个请求必须在前一个请求响应到达之后才能发送。即如果前一个请求响应一直不达到那么下一个请求也不会发送,后面的一直被阻塞。

HTTP/1.1 标准化的协议

基于上面的1.0的缺点,1.1做了如下优化:

  • 首先是长连接。HTTP/1.1增加了一个 Connection 字段,通过设置 Keep-Alive 可以保持 HTTP 连接不断开,避免了每次客户端与服务器请求都要重复建立释放建立TCP连接,提高了网络的利用率。如果客户端想关闭 HTTP 连接,可以在请求头中携带 Connection: false来告知服务器关闭请求。
  • 其次是 HTTP/1.1支持请求管道化(pipelining)。基于 HTTP/1.1 的长连接,使得请求管线化成为可能。管线化使得请求能够“并行”传输。举个例子来说,假如响应的主体是一个 html 页面,页面中包含了很多 img,这个时候 keep-alive 就起了很大的作用,能够进行“并行”发送多个请求。
  • 在HTTP/1.1 中增加 Host 请求头字段。我们可以在一台 WEB 服务器上可以在同一个IP地址和端口号上使用不同的主机名来创建多个虚拟 WEB 站点。
  • HTTP/1.1 还提供了与身份认证、状态管理和 Cache 缓存等机制相关的请求头和响应头。
  • HTTP/1.1 支持断点续传。

这里要说的是,HTTP/1.1 管道化所谓的并行传输其实并未做到真正的并行。服务器必须按照客户端请求的先后顺序依次回送相应的结果,以保证客户端能够区分出每次请求的响应内容。即管道化做的事情是把先进先出的队列从客户端迁移到了服务器,由服务器来维护这个状态。

但是在服务器的响应是有先后顺序的。比如:
客户端同时发送两个请求:

  • 请求获取 html 资源;
  • 请求获取 css 资源;
    这时候在服务器是 css 资源先准备好,但是服务器还是会等 html 资源准备好先发送 html 资源,等响应完毕再发送css资源。可见所谓的管道化技术还是无法解决 “阻塞” 的问题。同时,因为管道化技术存在各种各种的问题,浏览器厂商要么直接关闭该功能,要么就直接不支持,所以实际上该功能并没有被用到。

目前浏览器厂商采用的做法是针对同一个域名,最多允许同时发起6个请求,所以通过这种方式真正的做到了并行。

HTTP/2

HTTP/2 对于 HTTP1.1的改造和提升主要集中在性能上:多路复用,标头压缩,优先级划分和协议协商之类的一类关键功能。

  • HTTP/2是二进制协议而不是文本协议,不再可读
  • 这是一个复用协议,并行的请求能在同一个链接中处理,移除了 HTTP/1.x 中顺序和阻塞的约束
  • 压缩了 headers。因为 headers 在一系列请求中常常是相似的,其移除了重复和传输重复数据的成本
  • 允许服务器在客户端缓存中填充数据,通过一个叫服务器推送的机制来提前请求

HTTP的cookie机制

HTTP 是 无状态 的,这既是优点也是缺点。优点是服务器没有状态差异,可以很容易地组成集群,而缺点就是无法支持需要记录状态的事务操作。

那该怎么样让原本无 记忆能力 的服务器拥有 记忆能力 呢?服务器记不住,那就在外部想办法记住。相当于是服务器给每个客户端都贴上一张小纸条,上面写了一些只有服务器才能理解的数据,需要的时候客户端把这些信息发给服务器,服务器看到 Cookie,就能够认出对方是谁了。

cookie工作过程

这要用到两个字段:响应头字段 Set-Cookie 和请求头字段Cookie

当用户通过浏览器第一次访问服务器的时候,服务器肯定是不知道他的身份的。所以,就要创建一个独特的身份标识数据,格式是 key=value ,然后放进 Set-Cookie 字段里,随着响应报文一同发给浏览器。

浏览器收到响应报文,看到里面有 Set-Cookie,知道这是服务器给的身份标识,于是就保存起来,下次再请求的时候就自动把这个值放进 Cookie 字段里发给服务器。
因为第二次请求里面有了 Cookie 字段,服务器就知道这个用户不是新人,之前来过,就可以拿出 Cookie 里的值,识别出用户的身份,然后提供个性化的服务。

不过因为服务器的 记忆能力 实在是太差,一张小纸条经常不够用。所以,服务器有时会在响应头里添加多个 Set-Cookie,存储多个 key=value 。但浏览器这边发送时不需要用多个 Cookie 字段,只要在一行里用 ; 隔开就行。

cookie的属性

首先,我们应该设置 Cookie 的生存周期,也就是它的有效期,让它只能在一段时间内可用,就像是食品的 保鲜期 ,一旦超过这个期限浏览器就认为是 Cookie 失效,在存储里删除,也不会发送给服务器。

Cookie 的有效期可以使用 ExpiresMax-Age 两个属性来设置。

Expires 俗称 过期时间 ,用的是绝对时间点,可以理解为 截止日期 (deadline)。

Max-Age用的是相对时间,单位是秒,浏览器用收到报文的时间点再加上 Max-Age,就可以得到失效的绝对时间。

ExpiresMax-Age 可以同时出现,两者的失效时间可以一致,也可以不一致,但浏览器会优先采用 Max-Age 计算失效期。

比如在这个例子里,Expires 标记的过期时间是 GMT 2019 年 6 月 7 号 8 点 19 分 ,而 Max-Age 则只有 10 秒,如果现在是 6 月 6 号零点,那么 Cookie 的实际有效期就是 6 月 6 号零点过 10 秒 。

其次,我们需要设置 Cookie 的作用域,让浏览器仅发送给特定的服务器和 URI,避免被其他网站盗用。

作用域的设置比较简单,DomainPath 指定了 Cookie 所属的域名和路径,浏览器在发送 Cookie 前会从 URI 中提取出 host 和 path 部分,对比 Cookie 的属性。如果不满足条件,就不会在请求头里发送 Cookie。

使用这两个属性可以为不同的域名和路径分别设置各自的 Cookie,比如 /19-1 用一个 Cookie, /19-2 再用另外一个 Cookie,两者互不干扰。不过现实中为了省事,通常 Path 就用一个 / 或者直接省略,表示域名下的任意路径都允许使用 Cookie,让服务器自己去挑。

最后要考虑的就是Cookie 的安全性了,尽量不要让服务器以外的人看到。

写过前端的同学一定知道,在 JS 脚本里可以用 document.cookie 来读写 Cookie 数据,这就带来了安全隐患,有可能会导致 跨站脚本 (XSS)攻击窃取数据。

属性 HttpOnly 会告诉浏览器,此 Cookie 只能通过浏览器 HTTP 协议传输,禁止其他方式访问,浏览器的 JS 引擎就会禁用 document.cookie 等一切相关的 API,脚本攻击也就无从谈起了。

另一个属性 SameSite可以防范 跨站请求伪造 (XSRF)攻击,设置成SameSite=Strict 可以严格限定 Cookie 不能随着跳转链接跨站发送,而 SameSite=Lax 则略宽松一点,允许 GET/HEAD 等安全方法,但禁止 POST 跨站发送。

还有一个属性叫 Secure ,表示这个 Cookie 仅能用 HTTPS 协议加密传输,明文的 HTTP 协议会禁止发送。但 Cookie 本身不是加密的,浏览器里还是以明文的形式存在。

HTTP 缓存控制

服务器的缓存控制

  • 浏览器发现缓存无数据,于是发送请求,向服务器获取资源;
  • 服务器响应请求,返回资源,同时标记资源的有效期;
  • 浏览器缓存资源,等待下次重用。

服务器标记资源有效期使用的头字段是 Cache-Control,里面的值 max-age=30 就是资源的有效时间,相当于告诉浏览器, 这个页面只能缓存 30 秒,之后就算是过期,不能用。

max-age 是 生存时间 (又叫 新鲜度 缓存寿命 ,类似 TTL,Time-To-Live),时间的计算起点是响应报文的创建时刻(即 Date 字段,也就是离开服务器的时刻),而不是客户端收到报文的时刻,也就是说包含了在链路传输过程中所有节点所停留的时间。

比如,服务器设定 max-age=5,但因为网络质量很糟糕,等浏览器收到响应报文已经过去了 4 秒,那么这个资源在客户端就最多能够再存 1 秒钟,之后就会失效。

此外在响应报文里还可以用其他的属性来更精确地指示浏览器应该如何使用缓存:

  • no-store:不允许缓存,用于某些变化非常频繁的数据,例如秒杀页面;
  • no-cache:它的字面含义容易与 no_store 搞混,实际的意思并不是不允许缓存,而是可以缓存,但在使用之前必须要去服务器验证是否过期,是否有最新的版本
  • must-revalidate:又是一个和 no_cache 相似的词,它的意思是如果缓存不过期就可以继续使用,但过期了如果还想用就必须去服务器验证。

客户端缓存控制

其实不止服务器可以发 Cache-Control 头,浏览器也可以发 Cache-Control ,也就是说 请求 - 应答 的双方都可以用这个字段进行缓存控制,互相协商缓存的使用策略。

当你点 刷新 按钮的时候,浏览器会在请求头里加一个 Cache-Control: max-age=0 。因为 max-age 是 生存时间 ,max-age=0 的意思就是 我要一个最最新鲜的西瓜 ,而本地缓存里的数据至少保存了几秒钟,所以浏览器就不会使用缓存,而是向服务器发请求。服务器看到 max-age=0,也就会用一个最新生成的报文回应浏览器。

Ctrl+F5 的 强制刷新 又是什么样的呢?

它其实是发了一个 Cache-Control: no-cache ,含义和 max-age=0 基本一样,就看后台的服务器怎么理解,通常两者的效果是相同的。

条件请求

浏览器可以用两个连续的请求组成 验证动作 :先是一个 HEAD,获取资源的修改时间等元信息,然后与缓存数据比较,如果没有改动就使用缓存,节省网络流量,否则就再发一个 GET 请求,获取最新的版本。

但这样的两个请求网络成本太高了,所以 HTTP 协议就定义了一系列 If 开头的 条件请求 字段,专门用来检查验证资源是否过期,把两个请求才能完成的工作合并在一个请求里做。而且,验证的责任也交给服务器,浏览器只需坐享其成。

条件请求一共有 5 个头字段,我们最常用的是 if-Modified-SinceIf-None-Match 这两个。需要第一次的响应报文预先提供 Last-modifiedETag ,然后第二次请求时就可以带上缓存里的原值,验证资源是否是最新的。

如果资源没有变,服务器就回应一个 304 Not Modified ,表示缓存依然有效,浏览器就可以更新一下有效期,然后放心大胆地使用缓存了。

Last-modified 很好理解,就是文件的最后修改时间。ETag 是什么呢?

ETag 是 实体标签 (Entity Tag)的缩写,是资源的一个唯一标识,主要是用来解决修改时间无法准确区分文件变化的问题。

比如,一个文件在一秒内修改了多次,但因为修改时间是秒级,所以这一秒内的新版本无法区分。

再比如,一个文件定期更新,但有时会是同样的内容,实际上没有变化,用修改时间就会误以为发生了变化,传送给浏览器就会浪费带宽。

使用 ETag 就可以精确地识别资源的变动情况,让浏览器能够更有效地利用缓存。

ETag 还有 强 、弱 之分。

强 ETag 要求资源在字节级别必须完全相符,弱 ETag 在值前有个 W/ 标记,只要求资源在语义上没有变化,但内部可能会有部分发生了改变(例如 HTML 里的标签顺序调整,或者多了几个空格)。

还是拿生鲜速递做比喻最容易理解:

你打电话给超市, 我这个西瓜是 3 天前买的,还有最新的吗? 。超市看了一下库存,说: 没有啊,我这里都是 3 天前的。 于是你就知道了,再让超市送货也没用,还是吃冰箱里的西瓜吧。这就是 if-Modified-Since 和 Last-modified 。

但你还是想要最新的,就又打电话: 有不是沙瓤的西瓜吗? ,超市告诉你都是沙瓤的(Match),于是你还是只能吃冰箱里的沙瓤西瓜。这就是 If-None-Match 和 弱 ETag 。

第三次打电话,你说 有不是 8 斤的沙瓤西瓜吗? ,这回超市给了你满意的答复: 有个 10 斤的沙瓤西瓜 。于是,你就扔掉了冰箱里的存货,让超市重新送了一个新的大西瓜。这就是 If-None-Match 和 强 ETag 。

条件请求里其他的三个头字段是 If-Unmodified-Since If-Match 和 If-Range ,其实只要你掌握了if-Modified-Since 和 If-None-Match ,可以轻易地举一反三 。

一图胜千言:

浏览器缓存.png

useful code

check image URL is valid,including base64

async function checkImage(url){
     const res = await fetch(url);
     const buff = await res.blob();
     return buff.type.startsWith('image/');
}

一些命令解决一些问题

export HOMEBREW_BREW_GIT_REMOTE="https://mirrors.ustc.edu.cn/brew.git"
export HOMEBREW_CORE_GIT_REMOTE="https://mirrors.ustc.edu.cn/homebrew-core.git/"
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

LC: 3,189

LC3:给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

 输入: s = "abcabcbb"
 输出: 3 
 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

思路:滑动窗口,没有就进,有就剔除以及它左边的所有

  let lengthOfLongestSubstring = function(s) {
      let arr = new Array();
      let max = 0;
      for(let i=0; i < s.length; i++) {
        let index = arr.indexOf(s[i])
        if(index !== -1) {
          arr.splice(0,index + 1)
        }
        arr.push(s[i])
        max = Math.max(arr.length,max)
      }
      return max
    }


LC:189:给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
进阶:
尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。
你可以使用空间复杂度为 O(1) 的 原地 算法解决这个问题吗?

    输入: nums = [1,2,3,4,5,6,7], k = 3
    输出: [5,6,7,1,2,3,4]
    解释:
    向右旋转 1 步: [7,1,2,3,4,5,6]
    向右旋转 2 步: [6,7,1,2,3,4,5]
    向右旋转 3 步: [5,6,7,1,2,3,4]
   function rotate(nums,k){
      while(k>0){
          nums.unshift(nums.pop());
          k--
      }
      return nums;
   }

Python shell

Remove python [version number] completely step by step

 ls /Library/Frameworks/Python.framework/Versions/
sudo rm -rf /Library/Frameworks/Python.framework/Versions/[version number]
sudo rm -rf "/Applications/Python [version number]"
ls -l /usr/local/bin | grep '../Library/Frameworks/Python.framework/Versions/[version number]' 
cd /usr/local/bin/
ls -l /usr/local/bin | grep '../Library/Frameworks/Python.framework/Versions/[version number]' | awk '{print $9}' | tr -d @ | sudo xargs rm

计算机网络复习-TCP/IP

OSI模型、TCP/IP模型

OSI.png

  • 应用层:各种应用程序协议
  • 表示层:数据的格式化、数据加密解密,数据的压缩解压
  • 会话层:建立、管理、终止实体之间的会话链接
  • 传输层:数据的分段及重组,提供端到端的(可靠/不可靠)数据服务
  • 网络层:将分组从源端送到目的端,逻辑寻址,路由选择
  • 数据链路层:将分组的数据封装成帧,实现两个相邻节点之间的通信,差错检测
  • 物理层:在物理介质上传输数字(比特)信号,提供机械以及电气标准以及规约

TCP/IP协议

IP协议对应于网络层,TCP协议对应于传输层,主要解决数据如何在网络中传输,看下一个比较形象的比喻图:

tciIP_mail.png

通俗的解释:

  • IP地址能够锁定接收方或者发送方,物理表示就是一台计算机,而计算机通过网卡来接受以及发送数据包,数据包通过应用程序产生通过网卡发送,同时应用程序也监听着网卡发过来的数据包
  • 但每个应用程序没有必要监听所有网卡发过来的数据,所以用标识号来区分,为了数据安全,一个标识号只能被一个应用程序监听,这个标识号就是端口
  • 端口号和网卡以及进程之间的协作都被操作系统封装好了

TCP

Transmision Control Protocal 面向连接的传输控制协议

建立链接:3次握手

最开始的时候客户端和服务端都处于CLOSED状态,主动打开链接的为客户端,被动打开链接的是服务器

 tcp_established.gif

  • 服务端进入LISTEN 状态
  • 客户端发送 SYN=1 报文段(报文首部中的同步位),但不携带数据,同时选择一个初始序列号 seq=x ,然后客户端进入SYN—SENT状态(同步已发送)
  • 服务器收到请求报文后,如果同意,则发出确认报文,而确认报文中ACK=1,SYN=1 ,确认号为ack=x+1,同时也为自己初始化一个序列号seq=y, 然后服务端进入了SYN-RCVD (同步收到状态)
  • 客户端收到后向服务端发送确认报文。确认报文的ACK=1,ack=y+1,自己的序列号seq=x+1, 此时TCP连接建立,客户端进入ESTABLISHED状态
  • 服务端接受到客户端的确认后也进入ESTABLISHIED状态,接着双方就可以开始通信了

为什么客户端最后还要发送一次确认?
主要防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误

如果已经建立连接,但是客户端突然出现故障怎么办?
TCP设有一个保活计时器,客户端出现故障,服务端不可能一直等下去浪费资源。服务器每收到一个客户端的请求后都会重新复位这个计时器,一般为2小时,若两小时后客户端没有任何数据,服务器就会每个75秒发送一个探测报文段,连发10次还没有响应,就关闭连接。

释放连接:4次挥手

数据传输完毕后,双方都可以释放连接,客户端主动关闭,服务器被动关闭

tcp_closed.gif

  • 客户端发送释放数据报文,首部FIN=1,其序列号为seq=u,客户端进入FIN-WAIT-1状态

  • 服务端收到连接释放报文,发出确认报文,ACK=1,seq=u+1,并且带上自己的序列seq=v,此时服务端进入CLOSE-WAIT,需要注意的是服务端TCP此时处于半关闭状态,因为服务端若发送数据,客户端依然要接受。

  • 客户端接受到服务端的确认请求后,此时客户端就进入FIN-WAIT-2,等待服务端发送释放报文,在这之前还需要接收服务端发送的数据。

  • 服务端将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1, 由于半关闭状态,服务端很可能又发送了一些数据,假设此时的序列号为seq=w,此时服务端进入了LAST-ACK 状态,等待客户端确认

  • 客户端接受到服务器的连接释放后,发出确认,ACK=1,ack=w+1而自己的序列号为seq=u+1,此时客户端进入了TIME-WAIT ,注意测试TCP还没有释放,经过2*MSL(最长报文寿命)后,进入CLOSED状态

  • 服务端接收到客户端的确认后,立即进入CLOSED ,所以结束的比客户端早一些

为什么客户端最后还要等待2MSL?
MSL(maximum segment lifetime)

  • 保证客户端发送的最后一个ACK能够到达服务器,因为这个ACK可能丢失,站在服务器的角度,已经发送了FIN+ACK, 客户端还没有回应,可能没有收到,所以我再发一次。而客户端就能在这2个MSL时间段内收到这个重传的报文,接着给出回应,并且重启2MSL计时器
  • 防止类似与三次握手中提到的已经失效的链接请求报文段出现在本链接中,客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以是本连接持续的时间内所产生的所有报文段都从网络中小时,这样新的连接中不会出现旧连接的请求报文

为什么建立连接是3次握手,而关闭连接是4次挥手呢?
建立连接的时候,服务器在LISTEN状态下,收到建立连接请求的SYN报文后,会把ACK和SYN放在一个报文里发送给客户端
而关闭连接时候,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据,但还能接收数据,而且服务端可能还有数据没有发送完,所以可以立即关闭,也可以在发送数据给对方后,再发送FIN报文给对方来同意关闭连接,因此ACK和FIN一般是分开发送,从而导致多了一次。

通俗的理解

 A打电话给B
 
 A:听得到吗?
 B:听得到!你呢?
 A:我也听到了,出来烧烤?

 A:真好吃,走吧,
 B:等下,我去把帐结了
 B:好,走吧
 A:走!各自回家

费曼学习法

费曼学习法可以简化为四个单词:Concept (概念)、Teach (教给别人)、Review (回顾)、Simplify (简化)

举个栗子:

浏览器JS事件循环,调用堆栈,任务队列等一些知识 如何让这些知识印象深刻呢?

ByteDance Interview

记录下一些面试中的技术问题

  • CSS 实现九宫格
  • 实现一个HOC/hook ,点击组件外面让这个组件隐藏,DOM事件流
  • DOM 操作相关,node.contains 等等
  • EventLoop相关(browser / nodejs的不同点,以及是否记得哪个版本后来一致了) , RAF 是宏任务还是微任务
  • 链表的第K个最大节点
  • samesite 是什么,有什么方法可以去兼容ios9,前端视角
  • css 新特性

  • 说说CSP , 然后网络安全
  • 客户端缓存策略
  • CDN 相关,它如何提高下载速度的,用node实现一个文件下载,怎么实现
  • DOM树的广度遍历
  • webpack的tapable是否知道?插件机制
  • React hooks 的陷阱,看题说出问题 ,useEffect 的闭包问题
  • 为甚么 hooks 要写在顶部
  • 如何设计中后台主题化的,说出两种方案

  • 微前端沙箱如何实现
  • 实现一个google analysis ,热力图,pv, uv

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.