V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ryncv
V2EX  ›  前端开发

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

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

    背景是这样:公司一个后台系统,大概有四五个 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, 本地就再缓存一次数据
    wunonglin
        3
    wunonglin  
       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 也方便
    wunonglin
        6
    wunonglin  
       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
    用协商缓存不就好了
    wunonglin
        11
    wunonglin  
       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 那边
    kabob
        29
    kabob  
       2021-12-13 22:05:03 +08:00 via iPhone
    service-worker 了解一下
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   实用小工具   ·   3360 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 39ms · UTC 07:51 · PVG 15:51 · LAX 23:51 · JFK 02:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.