浏览器Disk Cache磁盘缓存及其协商缓存、及原生App和浏览器实现缓存的差异

目录

浏览器Disk Cache磁盘缓存及其协商缓存、及原生App和浏览器实现缓存的差异

1、Memory Cache和Disk Cache区别

1.1、Memory Cache

1.2、Disk Cache

1.2.1、Disk Cache的存取举例

1.2.2、Disk Cache的存取方式

2、缓存,按执行优先级次序分类

2.1、浏览器存储的自身行为

2.2、Service Worker

2.3、Memory Cache

2.4、Disk Cache(与http指令的cache匹配,故又名Http Cache)

2.5、Push Cache

3、Disk Cache缓存,按其功能的类型分类

3.1、强制缓存

3.2、协商缓存

3.2.1、当被浏览器“强制缓存”的资源,在服务端发生“Modified”改变时,浏览器这一侧,缓存将如何“更新”;

3.2.2、当被浏览器“强制缓存”的资源,在服务端是否可以给定一个“过期”的机制,过期后,浏览器这一侧,该如何处理,且如何如何“更新”缓存;

3.2.3、浏览器的“导航器”或“浏览器的内置js解释器引擎”,首次处理H5或Http请求的资源时,应当采用什么样的机制。

4、浏览器实现请求网络超大文件的本机存储的策略

4.1、针对非IndexDB的存储

4.2、使用IndexedDB存储

4.3、使用H5原生的serviceWorker技术

5、原生App和浏览器实现本机存储和缓存的差异


我们知道,在计算机中,数据存储,要么读写“内存”、要么读写“ 磁盘”,没有第三者。浏览器也不例外,其存取数据,要么读写“内存”、要么读写“磁盘”,也没有第三者。

“缓存”的目的:

无论是web应用,还是原生App应用,无论是在客户端,还是在服务端,应用为了提升执行的效率(体现时间、速度)和节省设备和网络的关键性能指标(比如网络带宽的开销、CPU利用率、内存耗用、硬盘读写的I/O负载)的开销,会考虑将一些“请求”的资源在“内存”中或在“磁盘”中“预备”好,需要的时候,直接提取出来使用,从而减少了:

网络的往返的次数;

数据的重复计算;

数据的重复提取;

数据量的大小。

浏览器“缓存”的目的:

◆  首先:应当考虑上述“通用”的“缓存”目的;

◆  其次:是缓解浏览器自身来自“内存”读写的负载的。浏览器内部的“内存管理模块”,会尽可能的使用高速内存以提高效率,当其内部代码逻辑,发现本机内存已吃紧,它会自动启用对“磁盘”储存来进行读写,“磁盘”储存即我们通常所说的“虚拟内存”。

◆  浏览器利用本机的“虚拟内存”:是操作系统提供的外部存储,用以扩展“内存”的使用,因为它本质上并不是真正的“内存”,所以称为“虚拟”;它是“硬盘”上的“分块”的页面文件,MsWindows的话,将其作为“ROM”来进行使用;“虚拟内存”的速度取决于磁盘I/O,其性能远低于“内存”的I/O。

◆  浏览器为了简化用户对上述对其内部“对外公开”的“内存”管理功能和“虚拟内存”功能的“引用”,按照www组织的定义,对暴露给用户的“存储”及其关联的“缓存”的概念、分类、功能和用法,进行了进一步的“划分”:

◇  “Service Worker方式的(即PWA的实现的基础)”Cache Storage:

https://developer.chrome.com/docs/devtools/progressive-web-apps/?utm_source=devtools#opaque-responses

◇  “非Service Worker方式的”Cache Storage:

本文实际测试一下浏览器的行为、浏览器的存储、与存储关联的“缓存”。

1、Memory Cache和Disk Cache区别

1.1、Memory Cache

◆浏览器自动的性能行为

◆存储位置:内存的地址及其空间

◆时效性:导航器刷新或浏览器关闭,即刻释放

1.2、Disk Cache

◆总是与Http的“请求-响应”相关

◆存储位置:磁盘中不同类型的存储路径

◆时效性:导航器刷新或浏览器关闭,不受影响

1.2.1、Disk Cache的存取举例

拿MSWindows来举例(不同OS操作系统平台,各异:包括各派别的手机操作系统、各服务器操作系统厂家或发起机构、各PC操作系统厂家或发起机构),存储位置:

我们知道,所有MSWindows应用,其统一的本机“用户数据”的存取路径,均为:

C:\Users\Administrator\AppData\Local\

(除非你修改了操作系统默认的“全局路径”)

现以\Google\Chrome浏览器的\User Data用户数据,默认的Local Storage加密数据举例:

C:\Users\Administrator\AppData\Local\Google\Chrome\User Data\Default\Local Storage\leveldb

它对应了浏览器控制台该位置的数据存取:

(图2)

除此之外,还有各种本机用户的应用的默认数据:

(图3)

“Disk缓存”就是上述的其中一类“用户数据”。

1.2.2、Disk Cache的存取方式

◆要么“用户”与“浏览器”的控制台“交互”(如图2);

◆要么以编程的方式:动态地请求其中的数据,可以是与浏览器相关的API的方式、可以是浏览器原生SDK软件开发包或IDE厂家对SDK编制的API的方式。但,均需受制于必要的“源”的“权限机制”或“征得所有者(用户)的许可”(如图2或图3)。

◆默认是按“源/域”进行分区的

2、缓存,按执行优先级次序分类

◆浏览器的存储about:blank

◆Service Worker

◆Memory Cache

◆Disk Cache(与http的指令cache匹配,故又名Http Cache)

◆Push Cache

◆......等等,其它缓存

现,分别概述一下:

2.1、浏览器存储的自身行为

当“导航器”中首次执行输入的Location的URL地址时,会强制触发Storage下的第一方和第三方的"域/源"、(如果有的话,同时会读写:)及其“Cookies”、“IndexedDB”:

◇Loacal Storage

◇Session Storage

◇Cookies

典型的引用,比如我们用导航器打开“腾讯云”的站点:https://cloud.tencent.com/

2.2、Service Worker

MsWindows下,其物理存取路径为:

C:\Users\Administrator\AppData\Local\Google\Chrome\User Data\Default\Service Worker

按照其Disk Cache缓存内容的不同,分别可以对这些“缓存位置”及其“缓存内容”,进行存取:

其结构如下:

需要注意的是,这个存储大小的配额数值:指的是:

如果使用了service worker并进行了addResourcesToCache缓存操作,在service worker模式下对cache storage的配额是没有限制的。仅仅在:在“非service worker环境”下,在没有使用indexedDB时,单次请求、单个文件的存储,不超过7m/个文件/次请求;

那么,在“非service worker环境”下,超了怎么办?我们应当使用技巧:就是在请求时,将大文件chunk分块成N多个小块文件,每个文件不超过阀值(7M,安全起见,均设置为5M,与普通非SW缓存的使用保持一致);在服务端一次性生成这些文件,客户端一次请求N多个chunked分块。

典型的应用情景,就是“分页”数据的“静默”提取:将“渲染主线程上下文”中所需的“每个分页”数据,在“非渲染主线程上下文”(SW的安全上下文)中一次性地全部分别fetch下来,保存到Cache Storage中,以便“渲染主进程window”中的"worker"(负责渲染的网页)根据需要,从缓存中读取。但是你会发现,如果1个59MB的Json文件,你下载会非常的耗时,而且它被一次性地渲染布局到页面中也会有“卡顿”发生,那么怎么办呢:就是采用上述办法,请求N多个chunked分块,服务端一次性生成这些文件,让“每个分页”只渲染和布局绘制1个chunked分块,这样在Cache Storage体现出来就是所有N个Json文件(每个chunked分片的Json文件大小 = 59MB/N <=5MB),Cache Storage中缓存的“每个Json文件”为“每个分页”提供本机的数据服务。

刷新或再次使用该“资源”,0KB,从磁盘缓存中提取,不再消耗网络和服务器时间(但是本机渲染和布局绘制的时间,仍旧是独立的,需要单独消耗的):

同理,利用“缓存更新技术”:可以比较Cache Storage中存储的数据,和服务端存取的数据,之间的“字节差异”,做客户端的“缓存更新一次性提交客户端维护的变化了的数据”。

◆ SW的Disk Cache:“默认”,是按“源/域”进行分区的,而且是按“顶级文档源”(地址栏中显示的来源);

◆ 当然:你也可以使用“不透明响应”,来绕过这种限制,来实现“跨域安全策略”;

◆ SW:也可以使用IndexedDB存储。

SW,现已被绝大多数浏览器内核,接受并支持,只有少数不支持(注意,不要将PWA和SW划等号,PWA需要依赖SW的技术而已),下图是iPhone 7下iOS 13.6的效果:

◆ 苹果的态度:

2018年起,Safari Technology Preview 48、macOS High Sierra 10.13.4 beta seed 2 和 iOS 11.3 beta seed 2及其之后,苹果便开始了对serviceWorker的支持和发布。
◆ 苹果对待serviceWorker的观点:

Service Worker API是在 WebKit 的多进程基础架构中实现的,它提供了安全性和性能优势。
◆ serviceWorker的启动运行和停止运行的机制:

由于 Service Worker 实例同时消耗内存和 CPU 时间,因此仅在需要时运行它们很重要。serviceWorker通常在最初由网页注册时启动。在正常情况下,当一个serviceWorker的分区中没有serviceWorker的客户端,在一个小的宽限期后,serviceWorker将被终止。每当需要一些交互时,serviceWorker都会重新启动。
◆ serviceWorker与存储和缓存:

serviceWorker和缓存API存储的信息将随着用户浏览内容而增长。为了只保留对用户有用的存储信息,WebKit 将在几周后(或苹果最新政策规定的时间期限)删除未使用的serviceWorker注册。几周后未打开的缓存也将被删除。Web 应用程序必须对任何被删除的单个缓存、缓存条目或serviceWorker具有弹性。
◆ 苹果Safari浏览器支持对serviceWorker的代码调试debug:
        苹果Safari浏览器的Web Inspector 支持调试serviceWorker(若是手机的话,需要手机usb与macOS电脑连调)。“开发”菜单中包含随时运行的serviceWorker列表。单击其中一个 service worker 条目的js时,将附加一个检查员到该serviceWorker。从这里,可以使用断点调试与 fetch 或 postMessage 事件相关的代码。检查器控制台也是使用 fetch API 在serviceWorker上下文中触发网络负载的好地方。也可以通过几行代码从控制台检查 service worker 缓存,比如:

// # 在各个平台通用的调测代码:
await fetch('_index.html')
await self.caches.keys()
cache = await self.caches.open('v1')
await cache.keys()
await cache.matchAll()

◆ iOS在https下支持SW,下图为安装状态:

下图为已激活状态:

但是iOS在http下不支持SW(理论上,所有平台SW都应当在https或安全上下文中作业),下图为提示状态:

总之,一句话,移动端,无论原生App也好、web应用也好,不同平台及其内置浏览器会有许多限制,我是将开发选项中很多,都打开了的;或者通过代码请求权限,拉起提示让“用户”授权:

◆ 检测支持情况,官方推荐站点1:

◆ 检测支持情况,官方推荐站点2:

Is service worker ready?

2.3、Memory Cache

通常,浏览器的导航器,在初次执行window.location的URL时,或重复刷新页面时,会考虑将如下资源优先进行“内存缓存Memory Cache”:

◆html的DOM解构:

优先级,最高,用于渲染、元素本身不缓存:

◆head中的:

优先级,最高:

◇除icon类型的(包括x-icon)以外的<link>资源,特别是style样式表的css文件;

icon类型的<link>资源---属于特殊类型,为Disk Cache(优先级:最高)

◆body中的:

◇页面中直接使用H5原生的fetch的src="路径"的资源,比如:

优先级(js文件或嵌入script中的js代码)中等:

<script src="../js/index.js"></script>

优先级(img、音视频类)低:

<img src="../img/test.png" alt="">等,再比如:

2.4、Disk Cache(与http指令的cache匹配,故又名Http Cache)

再次执行同样URL的导航window.location,或再次刷新页面,之前的“内存缓存Memory Cache”,将被”强制缓存“至"Disk Cache磁盘缓存"中,并且此时服务端若存在304协商机制的代码,同时"协商缓存"会生效,将其Etag唯一性缓存标识及缓存的Cache-Control过期控制信息返回给浏览器的"Disk Cache磁盘缓存"。

2.5、Push Cache

Push Cache与浏览器的“后端服务”代码相关:

3、Disk Cache缓存,按其功能的类型分类

◆强制缓存

◆协商缓存

3.1、强制缓存

当导航器或http请求,首次执行时,浏览器为了“性能”,首次强行的“缓存”至内存,再次执行相同URL请求时,浏览器“强制缓存”至磁盘。总之,“强制缓存”,是浏览器干出来的,与http和网络,原本并无干系

3.2、协商缓存

由于浏览器永远都期望强行的进行本机的“缓存”,那么当“资源变化”时,若它也“强制缓存”,那么必然会导致代码与视觉或数据之间“不符合逻辑”,怎么办呢?

代表App的浏览器的厂商,与代表代码的js、html和css的阵营和为html而生的http,它们之间坐下来商议,我们需要出一个“标准”:

为了共同的“性能”的目标,我们之间(浏览器和后端服务代码)需要明确几点:

3.2.1、当被浏览器“强制缓存”的资源,在服务端发生“Modified”改变时,浏览器这一侧,缓存将如何“更新”;

3.2.2、当被浏览器“强制缓存”的资源,在服务端是否可以给定一个“过期”的机制,过期后,浏览器这一侧,该如何处理,且如何如何“更新”缓存;

3.2.3、浏览器的“导航器”或“浏览器的内置js解释器引擎”,首次处理H5或Http请求的资源时,应当采用什么样的机制。

于是,代表这种“提议”的“标准”出来了,即rfc 2616中的“10.3.5 304 Not Modified”及其“关联标准”条目:

◆  If the client has performed a conditional GET request and access is

allowed, but the document has not been modified, the server SHOULD

respond with this status code. The 304 response MUST NOT contain a

message-body, and thus is always terminated by the first empty line

after the header fields.

如果客户端已执行条件GET请求,并且访问是允许的,

但文档还尚未被修改话,服务器应用此状态码进行响应。

304响应不得包含 消息正文message-body,

因此总是在标题字段header fields之后以第一个空行结束first empty line。

◆  The response MUST include the following header fields:

响应必须包括以下标题字段header fields:

◆  - Date, unless its omission is required by section 14.18.1

-日期,除非第14.18.1节“ ClockLess Origin Server Operation无时钟“源”服务器操作”中要求省略

◆  If a ClockLess origin server obeys these rules, and proxies and

clients add their own Date to any response received without one (as

already specified by [RFC 2068], section 14.19), caches will operate

correctly.

如果无时钟源服务器( ClockLess origin server)遵守这些规则,

代理或客户端将它们拥有的“日期Date”添加到接收到的任何没有日期的响应中

(如已由[RFC 2068]第14.19节规定),缓存将正确地运行。

◆  - ETag and/or Content-Location, if the header would have been sent

in a 200 response to the same request

-如果在对同一请求的200的响应中,标题header已经被导航器或代码执行了200 OK的发送,

则标记:ETag和/或Content Location

◆  - Expires, Cache-Control, and/or Vary, if the field-value might

differ from that sent in any previous response for the same

variant

-如果字段值与之前发送的相同响应的变量值不同,可以发送响应头:

过期Expires、缓存控制Cache-Control 和/或 更改Vary

◆  If the conditional GET used a strong cache validator (see section

13.3.3), the response SHOULD NOT include other entity-headers.

Otherwise (i.e., the conditional GET used a weak validator), the

response MUST NOT include other entity-headers; this prevents

inconsistencies between cached entity-bodies and updated headers.

如果条件GET使用了“强制缓存”验证器strong cache validator(请参阅第节13.3.3),

响应不应包括其他实体标头entity-headers。

否则(比如:条件GET使用“弱”验证器weak validator)响应不得包含其他实体标头;

这可以防止“缓存的实体主体cached entity-bodies”和“更新的标头updated headers”之间的不一致。

◆  If a 304 response indicates an entity not currently cached, then the

cache MUST disregard the response and repeat the request without the

conditional.

如果304响应指示当前实体未被缓存,则缓存必须并且是无条件地忽略响应

◆  If a cache uses a received 304 response to update a cache entry, the

cache MUST update the entry to reflect any new field values given in

the response.

如果缓存使用接收到的304响应来更新缓存条目,缓存必须更新条目以反映给定的响应中的任何新字段值。

概括起来,“协商”三条,即为“协商缓存”:

为了共同的“性能”和“可用性”的目标,“浏览器联盟一方”同“后端服务开发联盟和http网络一方”,一致明确了,如下的"w3c执行标准":

3.2.1、当被浏览器“强制缓存”的资源,再次请求“相同资源”时(即请求的URL不变),无论服务端的资源的名称或字节数是否变化,均需要“在本机做验证和效验”Etag标识及其对应的Control-Cache: max-age=***毫秒,must-revalidate: true的是否过期且重新验证的信息,效验该资源是否有效或过期:若未过期,则无需重新请求“服务端”,直接使用“本机缓存”的内容加载、渲染并绘制页面;若过期或无效,则浏览器让客户端的代码,重新发起“资源的网络请求”、“在服务端做验证和效验”处理,并据此重新“更新本机的缓存”;此过程,称为“协商缓存”验证和效验;同时,若存在no-cache,或Cache-Control: max-age=0;must-revalidate:true,没有缓存或无效,也需要做相应的“协商缓存”的“在服务端做验证和效验”处理 。

        no-store:“不要做任何缓存”,任何响应的内容都不走缓存,无论是强制缓存、还是协商缓存。

        private:默认,内容仅在UA客户端方可缓存,不能在代理服务器做缓存;
        public:默认,内容即可缓存到UA客户端,也可缓存到cdn等其它任何代理服务器。

3.2.2、服务端对浏览器“强制缓存”的资源设定并保留一个“过期”的副本copy,同时向浏览器的响应头写入一个“Cache-Control: max-age=***秒(为了兼容IE,若不使用缓存的情景:Cache-Control:no-cache 还附加了字段Pragma: no-cache )” 的过期字段 和 一个对缓存的唯一性“标记Etag(一般为base64格式的加密字符串等格式)”;浏览器在“缓存”时用同样的“标记Etag”来做本机存储和唯一性识别;

3.2.3、浏览器的“导航器”或“浏览器的内置js解释器引擎”,首次处理H5或Http请求的资源时:让本机代码向服务端发出xhr或fetch请求,同时将服务端的响应头的“标记Etag”和响应内容的结果,浏览器将响应消息同时写入本机“缓存”。

既然叫“协商”,就是:需要“浏览器执行前端代码”和“后端代码”,共同作协的结果,需要“前端开发人员”和“后端开发人员”,协商确定,共同一致的处理方法。

4、浏览器实现请求网络超大文件的本机存储的策略

4.1、针对非IndexDB的存储

首先,肯定是针对Disk Cache,无论是service worker,还是强制缓存或协商缓存;

其次,是请求的策略上,采用分块下载(chunked):浏览器客户端这一侧用“分片下载”来与服务端“协商请求”资源,而服务端则协商后采用将超大文件的资源,切割成N块(每块<=5MB的浏览器单个文件配额)的方式send发送响应给客户端,客户端存储到响应的Disk Cache,而读取或渲染时,以可读流的方式读取到内存,进行合并,当然此方式也受制于客户端“内存”的大小,还不是真正意义上的“超大文件”储存方案。

4.2、使用IndexedDB存储

使用IndexedDB技术,将不受制于单次请求单个文件的5MB配额的限制。理论上没有限制,IndexedDB官方并没有做特别的说明。大厂,一般采用此这种浏览器端的存储策略,比如我的博客:《大厂后台管理passportal的通行做法-之腾讯云研究》https://blog.csdn.net/pulledup/article/details/127488160 中,腾讯云就使用了此存储方案。

4.3、使用H5原生的serviceWorker技术

(如上“2.2、Service Worker”节所述,略;其中也可以结合使用IndexedDB来进行存储)。

5、原生App和浏览器实现本机存储和缓存的差异

原生App和浏览器实现缓存的差异,首先要从本机存储的差异说起:

比较项 原生App 浏览器 备注
本机存储的位置 ◆电脑端:在目录访问权限框架内不限 ◆浏览器自身的沙盒内的指定分类目录,分别存取不同的存储类型;并分别公开在浏览器devtool不同的分区 比如Android可参考:我的博文 
◆移动端:总的,在“沙盒”内不限;细分,在沙盒内根据分类分子路径存取文件。
本机存储磁盘占用配额 ◆均不限 ◆单次请求中的单个文件:配额<=5M  
本机存储的方法 ◆完全取决于客户端的请求和服务端的响应,在内存和磁盘之间,相互转储 ◆service worker:灵活,可自主决定哪些需要存储或缓存,以及方式等  
◆非service worker方式,取决于:
  ◇ 浏览器自身的行为
  ◇ Memory Cache的存取特点
  ◇ Disk Cache的存取特点和存取的位置分类的关系
  ◇ Push Cachedeng background service的存取特点和存取位置分类的关系

然后,在它们各自的“本机存储”的基础上,对应其缓存的读写,即可,总的来说,就是从“内存”到“磁盘”之间的相互“转储”。细节,略。

喜欢的,就收藏并点个赞,鼓励我继续技术的原创写作及经验分享:

《大厂后台管理passportal鉴权登录的通行做法-之腾讯云研究》:

https://blog.csdn.net/pulledup/article/details/127488160

浏览器Disk Cache磁盘缓存及其协商缓存、及原生App和浏览器实现缓存的差异相关推荐

  1. disk cache(磁盘缓存) 和 memory cache(内存缓存)的区别

    disk cache(磁盘缓存) 和 memory cache(内存缓存)的区别 同: 都属于强缓存,现在浏览器缓存存储图像和网页等(主要在磁盘上),而你的操作系统缓存文件可能大部分在内存缓存中. 使 ...

  2. uni-app app清除app缓存,使用一段时间app数据图片等缓存清理,记录一下

    uni-app  app清除本地的缓存,app使用一段时间缓存数据导致app卡顿,清理缓存 记录一下操作 设置里面有清理缓存按钮,点击按钮清除缓存 export default {components ...

  3. jq 自动打开浏览器_jQuery之解析判断当前页面打开端(APP或浏览器)的方法

    本篇文章主要讲述jQuery之解析判断当前页面打开端(APP或浏览器)的方法,希望阅读本篇文章以后大家有所收获,帮助大家对相关内容的理解更加深入. 一.代码如下: function check_use ...

  4. 浏览器缓存(一):强缓存 MEMORY CACHE 和 DISK CACHE

    关于memory cache 和 disk cache 随便浏览一个网站: 首次打开,或者开启浏览器的 Disable Cache(浏览器的Network下, 与Preserve log同级别),在s ...

  5. syslog 向内存中缓存_动画:深入浅出从根上理解 HTTP 缓存机制及原理!

    HTTP 缓存,对于前端的性能优化方面来讲,是非常关键的,从缓存中读取数据和直接向服务器请求数据,完全就是一个在天上,一个在地下. 我们最熟悉的是 HTTP 服务器响应返回状态码 304,304 代表 ...

  6. 浏览器缓存:memory cache、disk cache、强缓存协商缓存等概念

    文章目录 分类 memory cache disk cache Service Worker Push Cache 缓存过程 强缓存 1.Expires 2.Cache-Control Expires ...

  7. 浏览器缓存 from memory cache与from disk cache详解

    在chrome浏览器中的控制台Network中size栏通常会有三种状态 from memory cache from disk cache 资源本身的大小(如:1.5k) 那么问题来了 三种区别在哪 ...

  8. chrome浏览器缓存 from disk cache

    今天遇到个问题,同样的两个前端项目,服务器也一样,但是有一个项目的接口出现status:200 (from disk cache),之前从没遇见过,在此记录一下.解决办法:只要清除浏览器缓存(更多工具 ...

  9. linux 编译缓存,Linux磁盘缓存(disk cache)详解

    在Linux系统里通过free命令,我们经常可以看到类似下面的输出: $ free -m total used free shared buffers cached Mem: 24097 21665 ...

最新文章

  1. ffplay.c学习-1-框架及数据结构
  2. Linux安装Nginx使用负载均衡
  3. IIS服务器上增加mp4格式MIME 类型映射设置具体步骤
  4. javascript学习系列(14):数组中的indexOf方法
  5. 调试某游戏副本中的加亮提示信息思路
  6. MySql Cluster 安装,Centos,双管理,多数据,多SQL节点
  7. win10自带的打印机服务器,win10系统打印服务器安装设置的详细方法
  8. android实现弹框动画,android对话框弹出方式动画
  9. 最新版MATLAB怎么运行代码,matlab怎么运行代码
  10. 第12期 《博观而约取,厚积而薄发》6月刊
  11. .rpt 文件怎麽打開?Crystal Reports 打開.rpt失敗 ?
  12. 年薪200万是怎样的一种体验?
  13. How to learn a new technology
  14. touchjs中,touch的使用
  15. Oracle-表的创建与管理
  16. 易语言网络访问响应中文乱码
  17. 【Paper】Word2Vec:词嵌入的一枚银弹
  18. 联想erazert410_联想erazert410
  19. Win Server 2022 下自动化测试,Appium连接蓝叠模拟器
  20. UILocalNotification实现本地的闹钟提醒

热门文章

  1. “U盘、手机卡、内存卡出错,打开提示“未格式化”,里面有重要的资料~别着急,就这样试试吧~”【U盘、内存卡使用时意外断电或死机导致U盘无法打开,提示未格式化,解决思路参考】
  2. ceph s3 rgw配置
  3. avast oracle 拦截_Avast Internet Security免费版下载-网络保护与病毒拦截工具 v20.8.56 免费版 - 安下载...
  4. 05.视频播放器内核切换封装
  5. 天旦发布开源端口镜像工具,AIOps实践推动数字化转型
  6. 3.1无名管道、命名管道
  7. [精选网址]MSDN简体中文在线
  8. CHM帮助文档打开为空白的解决办法
  9. 今天分享一个关于微商的套路。
  10. Revit2016 笔记06