V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
ryncv
5.3D

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

  •  
  •   ryncv · Dec 13, 2021 · 3797 views
    This topic created in 1595 days ago, the information mentioned may be changed or developed.

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

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

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

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

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

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

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

    这有个大量数据导出的示例
    IvanLi127
        26
    IvanLi127  
       Dec 13, 2021 via Android
    后端动得了的话,加个协商缓存的标头吧,不能啥活都前端揽下呐
    maplelin
        27
    maplelin  
       Dec 13, 2021
    service-worker 可以根据条件缓存,至于更新你可以单独更新 service-worker 的注册版本就行了
    KitAndrewLee
        28
    KitAndrewLee  
       Dec 13, 2021
    直接把文件写到 json 文件里面,然后上 CDN,接口请求的时候直接转发到 CDN 那边
    StillNotYet
        29
    StillNotYet  
       Dec 13, 2021 via iPhone
    service-worker 了解一下
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   5315 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 75ms · UTC 01:18 · PVG 09:18 · LAX 18:18 · JFK 21:18
    ♥ Do have faith in what you're doing.