背景是这样:公司一个后台系统,大概有四五个 API ,数据量都比较大( gzip 后大约还是有 3M )。数据内容相对稳定,不会很频繁的更新,大约一两周会更新维护一下。 如果每次访问页面都调用原始接口,会太慢,而且会占用很多下载带宽。因为一些原因,后台也没办法做成按需加载的,必须一次性全量返回。
现在方案是,第一次用户访问的时候,把接口数据全部存到 Localstorage 里面,刷新后检测到本地有数据就不请求服务器了,但是这样会存在缓存没法更新的问题,需要用户手动清理浏览器缓存。
求助一下有什么比较好的方案可以解决这个?
1
fengfuliu 2021-12-13 14:03:43 +08:00
写个新请求每次都请求,仅下发一个字段表示是否为新数据,version:1.1 之类的
|
2
mineralsalt 2021-12-13 14:04:57 +08:00
在服务端做一个 hash 对比 api, 每次使用数据的时候, 请求 api,提交本地缓存的数据 hash, 服务端进行最新数据的 hash 比对, 如果有更新就返回 true, 本地就再缓存一次数据
|
3
wunonglin 2021-12-13 14:05:11 +08:00 1
那么大的数据建议放 indexeddb ,不要放 localstorage 。另外存的时候用版本号标记下(就 updated_at 就行了)。后端给接口获取这个,有变化就拉数据
|
4
mineralsalt 2021-12-13 14:05:58 +08:00
@mineralsalt 这种方案的好处是免维护, 1L 的版本方案会增加工作量
|
5
66beta 2021-12-13 14:06:59 +08:00
写到 json 文件里,将来上 CDN 也方便
|
6
wunonglin 2021-12-13 14:07:53 +08:00 1
@mineralsalt #4 你这个费时费力,还造成没必要的前端和后端的读取计算
|
7
mineralsalt 2021-12-13 14:09:20 +08:00
@wunonglin 辛苦一次造福未来啊, md5 一下, 也没什么计算量和工作量吧, 工具函数都是现成的, 搞版本号以后维护多麻烦
|
8
tabris17 2021-12-13 14:12:40 +08:00 1
静态化啊,HTTP 请求用 If-Modified-Since 头部就好了
|
9
ryncv OP @wunonglin #3 indexdb 会比 localstorage 有明显优势吗?之前试过 indexdb ,感觉不是很稳定,有几次用户反馈看不到内容,我现场用 chrome 工具发现 indexdb 一直在转 loading 或者是直接显示白的,感觉就像初始化失败了之类的,需要把整个 indexdb 删了刷新才行。
|
10
ryougifujino 2021-12-13 14:15:25 +08:00
用协商缓存不就好了
|
11
wunonglin 2021-12-13 14:16:08 +08:00
@ryncv #9 localstorage 限制 5M 。在你不能保证数据大小的情况下(你都 3m 了,危险边缘),用 localstorage 是不保险的。再加上 indexdb 有索引之类的,可以直接取你需要的数据而不用全拿出来(当数据库用),indexdb 对于大数据来说是最优的解法
|
12
ryncv OP |
13
ryougifujino 2021-12-13 14:31:36 +08:00
@ryncv #12 后台是要稍微改一下的,但不麻烦
|
14
3dwelcome 2021-12-13 14:44:47 +08:00
协商缓存没法用啊,楼主数据集合有可能是增量更新,那就意味着可以增量下载。
而协商缓存就是简单粗暴的过期全部重下资源,没意义的,还不如自己发 hash 校验。 我以前的同事,是客户端单方面去向服务器,同步数据集合。 每条记录都有最后修改时间,只要服务器端的数据,大于客户端请求时间戳,都全部给客户端发过去。 |
15
makelove 2021-12-13 16:17:34 +08:00
我当前用的是存 indexeddb ,数据上有个自增版本号,定期用版号查后端有没有更新,有就重新下载保存。
indexeddb 各种浏览器都非常稳,就是在 safari 下有时会莫名被清了数据,非常奇怪,果然是三流内核。 |
18
makelove 2021-12-13 16:58:14 +08:00
@ryncv 当然了这个还不够,还要做个定时防止有人从不关 tab ,再监控浏览器 tab 切换事件,切回来时如果有一阵没检查也去查一下
|
20
whypool 2021-12-13 17:55:00 +08:00 via Android
写个脚本把 api 跑成 json 文件丢 cdn ,改的时候前端改一下引用 json 版本,一劳永逸
|
21
Rush9999 2021-12-13 17:57:21 +08:00
|
22
luvsic 2021-12-13 18:16:30 +08:00
https://github.com/vercel/swr
缓存+刷新都有了 |
23
kekxv 2021-12-13 18:35:31 +08:00 via iPhone
用 jsonp 就行,时间不要用秒,用日或者自己设定想要的间隔
|
24
netnr 2021-12-13 19:16:24 +08:00 via Android
服务端把 json 写入文本,再打包 ZIP ,前端下载 ZIP 包解压读取文本解析 JSON
|
25
netnr 2021-12-13 19:19:24 +08:00 via Android
|
26
IvanLi127 2021-12-13 19:27:49 +08:00 via Android
后端动得了的话,加个协商缓存的标头吧,不能啥活都前端揽下呐
|
27
maplelin 2021-12-13 20:54:51 +08:00
service-worker 可以根据条件缓存,至于更新你可以单独更新 service-worker 的注册版本就行了
|
28
KitAndrewLee 2021-12-13 21:54:31 +08:00
直接把文件写到 json 文件里面,然后上 CDN,接口请求的时候直接转发到 CDN 那边
|
29
kabob 2021-12-13 22:05:03 +08:00 via iPhone
service-worker 了解一下
|