V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
helee9199
V2EX  ›  程序员

js 有清除缓存的方法么

  •  
  •   helee9199 · 2022-04-28 18:24:24 +08:00 · 5374 次点击
    这是一个创建于 701 天前的主题,其中的信息可能已经有所发展或是发生改变。

    医院项目 项目有时修改到 js 后 替换到生产环境 有时有效 有时无效 清理缓存后则会好 但又不太好每次都让 user 清理缓存,他们也不一定会 所以有办法 清理缓存的方法么 目前想的是写到到登录入口 登录成功后就清理缓存 保证每次登录后是没有缓存的

    78 条回复    2022-04-30 23:34:58 +08:00
    zingwu
        1
    zingwu  
       2022-04-28 18:27:04 +08:00
    我们用的 umi ,每次更新打包完 hash 值变了会刷新
    3dwelcome
        3
    3dwelcome  
       2022-04-28 18:31:23 +08:00
    这个 JS 没生效,一般都是服务器没有配置好。JS 没过期,自然是不会重新下载一次的。

    可以参考一下我以前的发帖,/t/830203
    WeiYuanStudio
        4
    WeiYuanStudio  
       2022-04-28 18:31:32 +08:00
    打包 hash 后缀可解
    helee9199
        5
    helee9199  
    OP
       2022-04-28 18:36:39 +08:00
    @3dwelcome emm 因为项目比较老,我们更新项目的方式还比较传统. 量大的时候就给完整包
    不涉及后台 jar 的时候.就单独给差异进行替换
    所以没有具体的某个页面去清缓存
    目前就希望每次登录的时候整个项目清缓存
    不知道那些清缓存插件是怎么实现的
    希望有个接口 调一下就能实现
    yunying
        6
    yunying  
       2022-04-28 18:43:51 +08:00
    让用户浏览器安装插件跟让用户手动清楚缓存没什么区别,治标不治本。还是得对前段所有静态资源做缓存管理,根据开发成本和场景,可前后端都做或者单做其中一端看看能不能解决
    oneisall8955
        7
    oneisall8955  
       2022-04-28 18:59:54 +08:00   ❤️ 10
    <a href="javascript:alert('清除成功');">清除缓存</a>
    helee9199
        8
    helee9199  
    OP
       2022-04-28 19:01:47 +08:00
    @yunying
    老项目 老技术 不知道有什么方案可以解决
    可以说点关键字我搜索下么?
    elevioux
        9
    elevioux  
       2022-04-28 19:03:42 +08:00 via Android
    js 地址加版本号?
    helee9199
        10
    helee9199  
    OP
       2022-04-28 19:06:08 +08:00
    @elevioux 这个情况之能解决一个页面呀 ,项目那么多页面 都有引乱七八糟的 js 啥的 不太好实现
    目前只求能一次性清理项目页面缓存
    hgc81538
        11
    hgc81538  
       2022-04-28 19:13:56 +08:00
    script_1.js?<script_1.js 在文件系統的最後修改 unixtime>
    script_2.js?<script_2.js 在文件系統的最後修改 unixtime>

    e.g. script_1.js?1651144341
    bearice
        12
    bearice  
       2022-04-28 19:16:57 +08:00
    难道不能干脆不缓存么?反正是内部访问,那点儿量也不至于说不缓存就能咋样。
    helee9199
        13
    helee9199  
    OP
       2022-04-28 19:24:12 +08:00
    @bearice 怎样不缓存呢
    就是想不缓存
    比如有个 bug 我改了 js 我们目前是把这个 js 拿去替换文件
    结果护士发现 没生效, 然后一沟通教他清缓存 ,然后就好了
    但是这不是个办法, 所以才想说如何清缓存 或者不缓存.
    bearice
        14
    bearice  
       2022-04-28 19:25:01 +08:00
    helloet
        15
    helloet  
       2022-04-28 20:28:10 +08:00
    响应头 Cache-Control: no-store
    ClericPy
        16
    ClericPy  
       2022-04-28 21:50:59 +08:00
    别折腾 no-cache

    比较简单的方案前面提到了, js cdn 刷新了以后, 带冗余参数 ?v=xxxx, 这里的 xxxx 一般不用时间戳, 就用 js 计算出来的 md5 就行了. 不过后端得跟着一起发版...

    话说缓存这东西不是走 etag 的么
    Xhack
        17
    Xhack  
       2022-04-28 21:51:49 +08:00   ❤️ 2
    alter("缓存清楚成功")
    ClericPy
        18
    ClericPy  
       2022-04-28 21:53:03 +08:00
    @ClericPy 上面说错, 后端不一定要发版, 前后端隔离 HTML 也是前端项目的话就没事了

    虽然还是习惯 etag 什么的
    Yamdr
        19
    Yamdr  
       2022-04-28 21:56:15 +08:00
    <script src="xxx.js?v=7"></script>
    Yamdr
        20
    Yamdr  
       2022-04-28 21:57:04 +08:00
    <script src="xxx.js"></script>

    加上一个版本号
    <script src="xxx.js?ver=数字"></script>
    ImmerTry
        21
    ImmerTry  
       2022-04-28 22:49:00 +08:00
    遇到和题主一样的问题
    Osk
        22
    Osk  
       2022-04-28 22:49:21 +08:00
    不想动太多就向楼上的那样给 url 加 hash, 浏览器就会重新请求新文件了
    gamexg
        23
    gamexg  
       2022-04-28 23:05:56 +08:00
    在根目录建立不同版本的不同路径
    即把原来这样的 url http://www.abc.com/web1.html 改为 http://www.abc.com/版本号 /web1.html 或 改为 http://版本号.www.abc.com/web1.html
    登录页面跳转到最新版本地址。
    gamexg
        24
    gamexg  
       2022-04-28 23:12:42 +08:00
    另外,Service Workers 可能也能实现需求,印象这个可以拦截自身网站的请求并修改。
    rekulas
        25
    rekulas  
       2022-04-28 23:30:05 +08:00
    还可以把资源文件单独放个域名,相当于内部简陋版 cdn,通过 etag 等 header 进行缓存管控,你就可以随意控制缓存了,比如代码发布后自动更新清除缓存
    lk920724
        26
    lk920724  
       2022-04-29 00:40:20 +08:00
    学习一下其他做法,mark~
    yuzo555
        27
    yuzo555  
       2022-04-29 01:01:56 +08:00
    标准的做法是通过 Cache-Control: max-age=600 来控制浏览器缓存一个文件的时间,600 是秒数;
    或者不在乎服务器压力的话直接 Cache-Control: no-cache 不缓存;

    但是如果客户端比较多样化,有些垃圾浏览器很可能是只判断后缀不遵守这个规则的。
    最灵活的方式还是直接在网页代码里加 URL 参数 queryString ,例如 a.js?ver=202204290056 ,每次更新用 ver 记录版本号或者更新时间,这样浏览器就不会读旧缓存。

    上面说的 ETag 或者 Last-Modified ,不符合楼主这个场景,这俩是要 [等到浏览器认为缓存过期了] ,然后去服务器请求,服务端判断客户端请求头里的 If-None-Match 或者 If-Modified-Since ,如果服务器认为客户端的版本不需要更新,可以直接返回一个 304 Not Modified ,节省传输流量用的。
    ch2
        28
    ch2  
       2022-04-29 01:09:37 +08:00
    每次更新后生成的 js 都用 hash 命名,只更改 index.html 引用的 js 文件名,这样就能够保证用户使用的 js 要么全是旧版的,要么全是新版的,你只要更新一个 index.html 就行了
    Zy143L
        29
    Zy143L  
       2022-04-29 02:00:29 +08:00 via Android
    + hash 加版本号 这都是老生常谈的问题了
    mozhizhu
        30
    mozhizhu  
       2022-04-29 02:42:43 +08:00
    没打开之前,就知道一定有 alert <_<
    dartabe
        31
    dartabe  
       2022-04-29 02:48:19 +08:00
    Mark. 看来 no-cache 并不是什么好方案
    yunye
        32
    yunye  
       2022-04-29 02:51:34 +08:00
    前端获取当前时间戳,然后拼接一下 xxx.js?ver=时间戳
    IvanLi127
        33
    IvanLi127  
       2022-04-29 08:31:56 +08:00 via Android
    如果你打开 devtools 勾选了禁用缓存能正常工作,那么加 no-cache 是一个有效且改动很小的方案。如果能在 nginx 上改的话,几乎稳得一批
    superfatboy
        34
    superfatboy  
       2022-04-29 08:47:23 +08:00
    修改一下 ,服务端 配置不就完事了,完全不缓存,内容部用的系统也没事
    ImmerTry
        35
    ImmerTry  
       2022-04-29 09:04:29 +08:00
    @superfatboy 是像楼上那样 在 nginx 上做改动吗
    superfatboy
        36
    superfatboy  
       2022-04-29 09:14:05 +08:00
    @ImmerTry 差不多,详细的配置,上网搜下就有
    unco020511
        37
    unco020511  
       2022-04-29 09:18:25 +08:00
    后面加上版本号呀
    bzw875
        38
    bzw875  
       2022-04-29 09:29:06 +08:00
    js 做不到,在 http 可以设置 Cache-Control 、ETag 、Expires 、Last-modified 。在前端构建工具( webpack 、rollup )给 js 和 css ,图片加上文件哈希前缀比如 uhu43824f.js
    PEAL
        39
    PEAL  
       2022-04-29 09:32:49 +08:00
    @bzw875 曾经我以为这样子就完全可以了,直到遇到了一个国企的 APP 端网页,死缓存,只能在系统清除该 APP 缓存才能清除
    liyunyang
        40
    liyunyang  
       2022-04-29 09:33:49 +08:00
    公司有一样的问题,up 有解决方案的时候 @一下我,233333
    liyunyang
        41
    liyunyang  
       2022-04-29 09:34:41 +08:00
    之前听说 js 后面加版本号,再微信浏览器里面会被过滤?不知道这个说法是否正确
    Felldeadbird
        42
    Felldeadbird  
       2022-04-29 09:39:44 +08:00
    楼主没说项目的页面是不是静态页。我假定你全是后端渲染。
    1. 不考虑带宽损耗,直接 xxx.js?time=随机值。
    2. xxx.js?v=全局版本号变量

    如果是静态页.
    1. 想办法定期更新静态页的代码。xxx.js?v=带上版本号

    如果是打包项目,就从打包源码上解决。每次打包就更新所有 js 的版本号。
    kangyan
        43
    kangyan  
       2022-04-29 09:40:19 +08:00
    webpack 打包不是可以加 hash 后缀嘛,OP 的项目不能上 webpack 是吧
    davin
        44
    davin  
       2022-04-29 09:58:15 +08:00
    强制缓存 vs 协商缓存了解一下
    bojackhorseman
        45
    bojackhorseman  
       2022-04-29 10:01:02 +08:00
    @oneisall8955 #7 哈哈哈哈,看到标题我就想到这个
    zloong
        46
    zloong  
       2022-04-29 10:03:15 +08:00
    如果是单页应用,打包后的资源文件都是带 hash 的,所以只要配置服务器不缓存 index.html 就可以了 https://www.jianshu.com/p/5e7d4030254a
    serge001
        47
    serge001  
       2022-04-29 10:05:07 +08:00   ❤️ 1
    先说一下最佳的实践方案:
    将 html 和资源文件分开两个域名部署,html 文件 cache-control:no-cache ;每次访问让浏览器都去请求一次服务器;资源文件每次发布加 hash/版本号,设置强缓存:cache-control:max-age=60000 每次加载资源文件都使用本地缓存

    对于你的问题,很明显就是服务器返回的 cache-control 响应头有问题,无脑的解决方案就是设置 cache-control: no-cache ;
    tyx1703
        48
    tyx1703  
       2022-04-29 10:08:03 +08:00 via iPhone
    @yuzo555 你说错了。no-cache 是忽略本地缓存时间,任然会带上 if-none-match 和 if-modified-since 请求头跟服务端协商。no-store 才是完全忽略本地缓存。
    serge001
        49
    serge001  
       2022-04-29 10:14:42 +08:00
    @tyx1703 协商缓存有什么问题
    tyx1703
        50
    tyx1703  
       2022-04-29 10:17:49 +08:00 via iPhone
    @serge001 服务端响应 304 的情况下还会采用之前的本地缓存。
    DICK23
        51
    DICK23  
       2022-04-29 10:21:15 +08:00
    内网项目,直接 cache-control: no-store 就完事了,再狠点就用打包工具生成 hash
    libook
        52
    libook  
       2022-04-29 10:30:33 +08:00
    编程有两大难题,第一个是起名字,第二个就是缓存管理。

    把代码尽可能移到外部引用的文件里,主页 html 尽可能简单,仅用于引用加载其他文件,然后关闭针对主页 html 的任何缓存,确保每次都从服务器拉最新版本,其他文件加缓存。
    每次更新代码,发布的时候都修改其他文件名,比如加一个随机字符串,然后在 html 中引用的时候引用新的文件,这样浏览器加载主页 html 之后,发现需要加载的其他文件跟已经缓存的路径不一样,就重新去拉新文件加载了。

    这一套现在有很多前端打包工具可以自动化完成,比如 webpack ,你要是项目不适合引入打包工具自己写一个脚本处理一下也可以。
    onionKnight888
        53
    onionKnight888  
       2022-04-29 10:33:30 +08:00
    ctrl+shift+R
    belin520
        54
    belin520  
       2022-04-29 10:36:50 +08:00
    location / {
    root /usr/local/nginx/html;
    index index.html;

    if ($request_filename ~* ^.*?.(html|htm)$) {
    add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
    }
    }
    jydeng
        55
    jydeng  
       2022-04-29 11:01:50 +08:00
    html 禁止缓存 + js 文件名 hash
    ImmerTry
        56
    ImmerTry  
       2022-04-29 11:25:25 +08:00
    @helee9199 OP 是部署到 tomcat 上的吧
    serge001
        57
    serge001  
       2022-04-29 11:30:01 +08:00
    @tyx1703 返回 304 那就是服务端的缓存控制出问题了
    rekulas
        58
    rekulas  
       2022-04-29 12:32:15 +08:00
    忽略我上面说的,header 确实没法更新缓存,还是只能加 url
    不过突然灵光一闪,如果不嫌麻烦,还可以试试 serviceworker ,相当于在前端搭建了个 CDN 。。
    lmshl
        59
    lmshl  
       2022-04-29 12:33:51 +08:00
    你正在访问的这个网站,是这么解决的:
    <script src="/assets/ad64c164f9c6f240aa3940ff6ace27be7981f830-combo.js" defer=""></script>
    WGNNN
        60
    WGNNN  
       2022-04-29 12:55:52 +08:00
    alert("清除缓存成功")
    helee9199
        61
    helee9199  
    OP
       2022-04-29 13:53:36 +08:00
    @ImmerTry 对的 而且 还是 jsp
    iqoo
        62
    iqoo  
       2022-04-29 14:01:10 +08:00   ❤️ 1
    最简单的办法,无需修改已有业务。

    新增一个脚本,定义哪些 URL 需强制更新,用 no-cache 模式去 fetch 即可:

    ```
    URL_LIST = [
    '/1.js',
    '/2.js',
    // ....
    ]

    URL_LIST.forEach(url => {
    fetch(url, {
    cache: 'no-cache',
    })
    })
    ```
    serge001
        63
    serge001  
       2022-04-29 15:04:02 +08:00
    果然面试题问 http 缓存还是能考出来一些问题的
    RabbitDR
        64
    RabbitDR  
       2022-04-29 15:40:51 +08:00
    现在的话,一种叫“revving”的技术用得比较多。
    https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Caching#%E6%94%B9%E8%BF%9B%E8%B5%84%E6%BA%90
    Huelse
        65
    Huelse  
       2022-04-29 16:27:10 +08:00
    所有的链接末尾都加上`?t=${new Date().getTime()}`
    oneisall8955
        66
    oneisall8955  
       2022-04-29 17:18:20 +08:00
    想起来了,以前写 thymeleaf 模板,可以这样,带上时间

    <script th:src="@{'/js/xxx.js?v='+${#httpServletRequest?.session?.lastAccessedTime}}"></script>

    jsp 应该也有差不多的语法吧
    OHyn
        67
    OHyn  
       2022-04-29 17:25:28 +08:00
    一个办法是服务器配置下,所有静态资源请求全加上 Cache-control: no-store 。直接干掉缓存。

    js 文件可以在 url 中加随机 query 强行请求。但 html 文件是另一个问题----个人感觉不在响应头里面动手脚的话,html 文件的缓存无解哎,一般都得配一下,html 文件不缓存。
    fstar
        68
    fstar  
       2022-04-29 17:47:13 +08:00   ❤️ 1
    HTTP 头字段只是标准,在什么时候缓存,什么时候不缓存。
    浏览器理论上会遵守,但有些细节可能不会遵守,或者会变化,比如 Chorme 80 版本后将 Cookie 的 SameSite 由原来的 None 改为了 Lax 。
    此外可能某个版本有实现上的 bug 。
    在技术群,有个群友说他的套壳 APP ,设置了 Cache-control: no-store 没效果,还是拿到的缓存内容。我觉得可能是 APP 套壳的浏览器有问题。

    所以,我想说的是,最好还是给文件名加哈希值,最稳妥。毕竟获取一个从来没访问过的资源,浏览器本地是不可能有缓存的。
    serge001
        69
    serge001  
       2022-04-29 20:41:16 +08:00
    @fstar 设置了 Cache-control: no-store 没效果, 会不会是设置之前本地已经有了缓存,这样情况下就不会立刻生效 要等本地缓存过期才行
    iyaozhen
        70
    iyaozhen  
       2022-04-29 21:00:37 +08:00
    话说回来面试还得问,https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Caching 能把这个吃透,真的不是应付面试,是真的有用
    xiangyuecn
        71
    xiangyuecn  
       2022-04-29 22:04:23 +08:00
    楼上叫 url 加 hash 的,怎么想的,他这种老项目 一个 js 内容变了,几百个 html 要改代码,就问你怕不怕😂

    web 服务器 加 Cache-Control 响应头,目测是最简单的解。其他方案 至少要有一次大规模修改代码

    改用户端环境?叫装插件?比改代码难多了!
    InDom
        72
    InDom  
       2022-04-29 22:26:36 +08:00
    其实 #62 楼已经给出解决方案了...
    duke807
        73
    duke807  
       2022-04-29 22:54:21 +08:00 via Android
    看我這個 cdencrypt 源碼 https://www.v2ex.com/t/832302

    主 js 對比其它 js 和資源文件的 sha 值,不對的話強制重新拉取

    js 和資源文件的文件名不用加入版本信息,方便版本管理
    duke807
        74
    duke807  
       2022-04-29 22:56:19 +08:00 via Android
    各文件 sha 值合成的列表用源碼目錄下的 tools 目錄下的腳本自動生成
    zyy314680012
        75
    zyy314680012  
       2022-04-30 09:56:59 +08:00 via Android
    我们 20 年前的时候都是 src 后面加版本号
    haah
        76
    haah  
       2022-04-30 10:18:27 +08:00
    正确的方法难道不是合理利用“缓存”么?
    litel
        77
    litel  
       2022-04-30 14:59:12 +08:00
    index.html 加上 no-cache 就好
    当然是在 js 有哈希变动的情况下
    lizhien
        78
    lizhien  
       2022-04-30 23:34:58 +08:00
    直接让他们用无痕不就完了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2731 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 39ms · UTC 12:42 · PVG 20:42 · LAX 05:42 · JFK 08:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.