请教一个大量 API 数据的前端缓存方案 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ryncv
5.3D
V2EX    前端开发

请教一个大量 API 数据的前端缓存方案

  •  
  •   ryncv 2021-12-13 14:00:55 +08:00 3463 次点击
    这是一个创建于 1407 天前的主题,其中的信息可能已经有所发展或是发生改变。

    背景是这样:公司一个后台系统,大概有四五个 API ,数据量都比较大( gzip 后大约还是有 3M )。数据内容相对稳定,不会很频繁的更新,大约一两周会更新维护一下。 如果每次访问页面都调用原始接口,会太慢,而且会占用很多下载带宽。因为一些原因,后台也没办法做成按需加载的,必须一次性全量返回。

    现在方案是,第一次用户访问的时候,把接口数据全部存到 Localstorage 里面,刷新后检测到本地有数据就不请求服务器了,但是这样会存在缓存没法更新的问题,需要用户手动清理浏览器缓存。

    求助一下有什么比较好的方案可以解决这个?

    29 条回复    2021-12-13 22:05:03 +08:00
    fengfuliu
        1
    fengfuliu  
       2021-12-13 14:03:43 +08:00
    写个新请求每次都请求,仅下发一个字段表示是否为新数据,version:1.1 之类的
    mineralsalt
        2
    mineralsalt  
       2021-12-13 14:04:57 +08:00
    在服务端做一个 hash 对比 api, 每次使用数据的时候, 请求 api,提交本地缓存的数据 hash, 服务端进行最新数据的 hash 比对, 如果有更新就返回 true, 本地就再缓存一次数据
    shakaraka
        3
    shakaraka  
    PRO
       2021-12-13 14:05:11 +08:00   1
    那么大的数据建议放 indexeddb ,不要放 localstorage 。另外存的时候用版本号标记下(就 updated_at 就行了)。后端给接口获取这个,有变化就拉数据
    mineralsalt
        4
    mineralsalt  
       2021-12-13 14:05:58 +08:00
    @mineralsalt 这种方案的好处是免维护, 1L 的版本方案会增加工作量
    66beta
        5
    66beta  
       2021-12-13 14:06:59 +08:00
    写到 json 文件里,将来上 CDN 也方便
    shakaraka
        6
    shakaraka  
    PRO
       2021-12-13 14:07:53 +08:00   1
    @mineralsalt #4 你这个费时费力,还造成没必要的前端和后端的读取计算
    mineralsalt
        7
    mineralsalt  
       2021-12-13 14:09:20 +08:00
    @wunonglin 辛苦一次造福未来啊, md5 一下, 也没什么计算量和工作量吧, 工具函数都是现成的, 搞版本号以后维护多麻烦
    tabris17
        8
    tabris17  
       2021-12-13 14:12:40 +08:00   1
    静态化啊,HTTP 请求用 If-Modified-Since 头部就好了
    ryncv
        9
    ryncv  
    OP
       2021-12-13 14:12:46 +08:00
    @wunonglin #3 indexdb 会比 localstorage 有明显优势吗?之前试过 indexdb ,感觉不是很稳定,有几次用户反馈看不到内容,我现场用 chrome 工具发现 indexdb 一直在转 loading 或者是直接显示白的,感觉就像初始化失败了之类的,需要把整个 indexdb 删了刷新才行。
    ryougifujino
        10
    ryougifujino  
       2021-12-13 14:15:25 +08:00
    用协商缓存不就好了
    shakaraka
        11
    shakaraka  
    PRO
       2021-12-13 14:16:08 +08:00
    @ryncv #9 localstorage 限制 5M 。在你不能保证数据大小的情况下(你都 3m 了,危险边缘),用 localstorage 是不保险的。再加上 indexdb 有索引之类的,可以直接取你需要的数据而不用全拿出来(当数据库用),indexdb 对于大数据来说是最优的解法
    ryncv
        12
    ryncv  
    OP
       2021-12-13 14:23:49 +08:00
    @tabris17 #8
    @ryougifujino #10
    last-modify 的方案考虑过,但是这些数据是存在数据库里的,不是静态文件。如果需要后台实现协商缓存那一套,需要做一定的改造吧。
    ryougifujino
        13
    ryougifujino  
       2021-12-13 14:31:36 +08:00
    @ryncv #12 后台是要稍微改一下的,但不麻烦
    3dwelcome
        14
    3dwelcome  
       2021-12-13 14:44:47 +08:00
    协商缓存没法用啊,楼主数据集合有可能是增量更新,那就意味着可以增量下载。

    而协商缓存就是简单粗暴的过期全部重下资源,没意义的,还不如自己发 hash 校验。

    我以前的同事,是客户端单方面去向服务器,同步数据集合。

    每条记录都有最后修改时间,只要服务器端的数据,大于客户端请求时间戳,都全部给客户端发过去。
    makelove
        15
    makelove  
       2021-12-13 16:17:34 +08:00
    我当前用的是存 indexeddb ,数据上有个自增版本号,定期用版号查后端有没有更新,有就重新下载保存。
    indexeddb 各种浏览器都非常稳,就是在 safari 下有时会莫名被清了数据,非常奇怪,果然是三流内核。
    ryncv
        16
    ryncv  
    OP
       2021-12-13 16:49:36 +08:00
    @makelove #15 “定期”的策略是怎样的呢? 每次进入页面先检查一下版本吗?
    makelove
        17
    makelove  
       2021-12-13 16:54:05 +08:00
    @ryncv 对,每次进都会检查,但先用旧的,如果检查结果出来有新的就直接刷新旧的显示
    makelove
        18
    makelove  
       2021-12-13 16:58:14 +08:00
    @ryncv 当然了这个还不够,还要做个定时防止有人从不关 tab ,再监控浏览器 tab 切换事件,切回来时如果有一阵没检查也去查一下
    ryncv
        19
    ryncv  
    OP
       2021-12-13 17:06:56 +08:00
    @makelove 这是一个思路,感谢。
    whypool
        20
    whypool  
       2021-12-13 17:55:00 +08:00 via Android
    写个脚本把 api 跑成 json 文件丢 cdn ,改的时候前端改一下引用 json 版本,一劳永逸
    luvsic
        22
    luvsic  
       2021-12-13 18:16:30 +08:00
    https://github.com/vercel/swr
    缓存+刷新都有了
    kekxv
        23
    kekxv  
       2021-12-13 18:35:31 +08:00 via iPhone
    用 jsonp 就行,时间不要用秒,用日或者自己设定想要的间隔
    netnr
        24
    netnr  
       2021-12-13 19:16:24 +08:00 via Android
    服务端把 json 写入文本,再打包 ZIP ,前端下载 ZIP 包解压读取文本解析 JSON
    netnr
        25
    netnr  
       2021-12-13 19:19:24 +08:00 via Android
    https://www.netnr.com/run/code/5328511666506473654

    这有个大量数据导出的示例
    IvanLi127
        26
    IvanLi127  
       2021-12-13 19:27:49 +08:00 via Android
    后端动得了的话,加个协商缓存的标头吧,不能啥活都前端揽下呐
    maplelin
        27
    maplelin  
       2021-12-13 20:54:51 +08:00
    service-worker 可以根据条件缓存,至于更新你可以单独更新 service-worker 的注册版本就行了
    KitAndrewLee
        28
    KitAndrewLee  
       2021-12-13 21:54:31 +08:00
    直接把文件写到 json 文件里面,然后上 CDN,接口请求的时候直接转发到 CDN 那边
    StillNotYet
        29
    StillNotYet  
       2021-12-13 22:05:03 +08:00 via iPhone
    service-worker 了解一下
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     983 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 22:29 PVG 06:29 LAX 15:29 JFK 18:29
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86