JavaScript 硬刷新当前页面

发布于 2024-08-18 15:23:24 字数 93 浏览 14 评论 0原文

如何通过 JavaScript 强制 Web 浏览器对页面进行硬刷新?
硬刷新意味着获取页面的全新副本并刷新所有外部资源(图像、JavaScript、CSS 等)。

How can I force the web browser to do a hard refresh of the page via JavaScript?
Hard refresh means getting a fresh copy of the page AND refresh all the external resources (images, JavaScript, CSS, etc.).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

梦忆晨望 2024-08-25 15:23:25

上面接受的答案除了在当今大多数新版本的网络浏览器上正常重新加载之外不再执行任何操作。我在最近更新的 Chrome 上尝试了所有这些,包括 location.reload(true)location.href = location.href。他们都没有工作。

我的解决方案是使用服务器端功能将非重复查询字符串附加到所有包含的源文件引用,如下例所示。

所以你还需要动态控制它何时保留上一个文件以及何时更新。唯一的问题是,当插件通过脚本执行文件包含时,您无法控制修改它。不用担心源文件泛滥。当旧文件取消链接时,它将被自动垃圾收集。

Accepted answer above no longer does anything except just a normal reloading on mostly new version of web browsers today. I've tried on my recently updated Chrome all those, including location.reload(true), location.href = location.href, and <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />. None of them worked.

My solution is by using server-side capability to append non-repeating query string to all included source files reference as like below example.

<script src="script.js?t=<?=time();?>"></script>

So you also need to control it dynamically when to keep previous file and when to update it. The only issue is when files inclusion is performed via script by plugins you have no control to modify it. Don't worry about source files flooding. When older file is unlinked it will be automatically garbage collected.

桃扇骨 2024-08-25 15:23:25

这是 2022 年的更新,有 2 种方法,考虑到 SPA 的 url 中带有 #

方法 1:

正如其他答案中提到的,一种解决方案是将随机参数放入查询字符串。在 javascript 中,可以通过以下方式实现:

function urlWithRndQueryParam(url, paramName) {
    const ulrArr = url.split('#');
    const urlQry = ulrArr[0].split('?');
    const usp = new URLSearchParams(urlQry[1] || '');
    usp.set(paramName || '_z', `${Date.now()}`);
    urlQry[1] = usp.toString();
    ulrArr[0] = urlQry.join('?');
    return ulrArr.join('#');
}

function handleHardReload(url) {
    window.location.href = urlWithRndQueryParam(url);
    // This is to ensure reload with url's having '#'
    window.location.reload();
}

handleHardReload(window.location.href);

不好的部分是它会更改当前的 url,有时,在干净的 url 中,对于用户来说,它可能看起来有点难看。

方法 2:

借鉴 https://splunktool.com/force-a-reload-of-page-in-chrome-using-javascript-no-cache,过程可能是先获取没有缓存的url然后重新加载页面:

async function handleHardReload(url) {
    await fetch(url, {
        headers: {
            Pragma: 'no-cache',
            Expires: '-1',
            'Cache-Control': 'no-cache',
        },
    });
    window.location.href = url;
    // This is to ensure reload with url's having '#'
    window.location.reload();
}

handleHardReload(window.location.href);

甚至可以与方法 1 结合使用,但我认为使用 headers 应该足够了:

async function handleHardReload(url) {
    const newUrl = urlWithRndQueryParam(url);
    await fetch(newUrl, {
        headers: {
            Pragma: 'no-cache',
            Expires: '-1',
            'Cache-Control': 'no-cache',
        },
    });
    window.location.href = url;
    // This is to ensure reload with url's having '#'
    window.location.reload();
}

handleHardReload(window.location.href);

This is a 2022 update with 2 methods, considering SPA's with # in url:

METHOD 1:

As mentioned in other answers one solution would be to put a random parameter to query string. In javascript it could be achieved with this:

function urlWithRndQueryParam(url, paramName) {
    const ulrArr = url.split('#');
    const urlQry = ulrArr[0].split('?');
    const usp = new URLSearchParams(urlQry[1] || '');
    usp.set(paramName || '_z', `${Date.now()}`);
    urlQry[1] = usp.toString();
    ulrArr[0] = urlQry.join('?');
    return ulrArr.join('#');
}

function handleHardReload(url) {
    window.location.href = urlWithRndQueryParam(url);
    // This is to ensure reload with url's having '#'
    window.location.reload();
}

handleHardReload(window.location.href);

The bad part is that it changes the current url and sometimes, in clean url's, it could seem little bit ugly for users.

METHOD 2:

Taking the idea from https://splunktool.com/force-a-reload-of-page-in-chrome-using-javascript-no-cache, the process could be to get the url without cache first and then reload the page:

async function handleHardReload(url) {
    await fetch(url, {
        headers: {
            Pragma: 'no-cache',
            Expires: '-1',
            'Cache-Control': 'no-cache',
        },
    });
    window.location.href = url;
    // This is to ensure reload with url's having '#'
    window.location.reload();
}

handleHardReload(window.location.href);

Could be even combined with method 1, but I think that with headers should be enought:

async function handleHardReload(url) {
    const newUrl = urlWithRndQueryParam(url);
    await fetch(newUrl, {
        headers: {
            Pragma: 'no-cache',
            Expires: '-1',
            'Cache-Control': 'no-cache',
        },
    });
    window.location.href = url;
    // This is to ensure reload with url's having '#'
    window.location.reload();
}

handleHardReload(window.location.href);
通知家属抬走 2024-08-25 15:23:25
window.location.href = window.location.href
window.location.href = window.location.href
几味少女 2024-08-25 15:23:25

使用搜索参数更改当前 URL 将导致浏览器将相同的参数传递到服务器,换句话说,强制刷新。

(不过,如果您对 Service Worker 使用拦截,则不能保证。)

  const url = new URL(window.location.href);
  url.searchParams.set('reloadTime', Date.now().toString());
  window.location.href = url.toString();

如果您想支持较旧的浏览器:

if ('URL' in window) {
  const url = new URL(window.location.href);
  url.searchParams.set('reloadTime', Date.now().toString());
  window.location.href = url.toString();
} else {
  window.location.href = window.location.origin 
    + window.location.pathname 
    + window.location.search 
    + (window.location.search ? '&' : '?')
    + 'reloadTime='
    + Date.now().toString()
    + window.location.hash;
}

也就是说,强制刷新所有 CSS 和 JS 有点费力。您可能需要执行相同的过程,为

document.querySelectorAll('link').forEach((link) => link.href = addTimestamp(link.href));

我不会费心使用 JS 示例,因为它可能只会引起问题。

您可以通过在编译 HTML 时在 JS 和 CSS 链接中添加时间戳作为搜索参数来避免这种麻烦。

Changing the current URL with a search parameter will cause browsers to pass that same parameter to the server, which in other words, forces a refresh.

(No guarantees if you use intercept with a Service Worker though.)

  const url = new URL(window.location.href);
  url.searchParams.set('reloadTime', Date.now().toString());
  window.location.href = url.toString();

If you want support older browsers:

if ('URL' in window) {
  const url = new URL(window.location.href);
  url.searchParams.set('reloadTime', Date.now().toString());
  window.location.href = url.toString();
} else {
  window.location.href = window.location.origin 
    + window.location.pathname 
    + window.location.search 
    + (window.location.search ? '&' : '?')
    + 'reloadTime='
    + Date.now().toString()
    + window.location.hash;
}

That said, forcing all your CSS and JS to refresh is a bit more laborious. You would want to do the same process of adding a searchParam for all the src attributes in <script> and href in <link>. That said it won't unload the current JS, but would work fine for CSS.

document.querySelectorAll('link').forEach((link) => link.href = addTimestamp(link.href));

I won't bother with a JS sample since it'll likely just cause problems.

You can save this hassle by adding a timestamp as a search param in your JS and CSS links when compiling the HTML.

南…巷孤猫 2024-08-25 15:23:25

更新刷新所有外部资源(图像、JavaScript、CSS等)

将其放入名为HardRefresh.js的文件中:

  function hardRefresh() {
    const t = parseInt(Date.now() / 10000); //10s tics
    const x = localStorage.getItem("t");
    localStorage.setItem("t", t);

    if (x != t) location.reload(true) //force page refresh from server
    else { //refreshed from server within 10s
      const a = document.querySelectorAll("a, link, script, img")
      var n = a.length
      while(n--) {
        var tag = a[n]
        var url = new URL(tag.href || tag.src);
        url.searchParams.set('r', t.toString());
        tag.href = url.toString(); //a, link, ...
        tag.src = tag.href; //rerun script, refresh img
      }
    }
  }

  window.addEventListener("DOMContentLoaded", hardRefresh);
  window.addEventListener("deviceorientation", hardRefresh, true);

此代码执行以下操作对每个访问者进行完全控制的强制硬刷新,以便任何更新都会显示而不会出现兑现问题。

重复的 DOM 渲染不是性能问题,因为第一次渲染来自缓存,并且它在从服务器重新加载页面的

最后刷新时间x存储在localStorage中。与当前时间t进行比较,在10秒内刷新。假设从服务器加载的时间不超过 10 秒,我们设法停止页面刷新循环,因此不要让它少于 10 秒。

对于页面的访问者来说,x != t 自从很久以前或第一次访问以来就为 true;将从服务器获取页面。然后 diff 小于 10 秒且 x == t,这将使 else 部分将查询字符串添加到 hrefsrc< /code> 有源需要刷新。

可以通过按钮或其他有条件的方式调用refresh()函数。完全控制是通过在代码中细化 URL 的排除和包含来管理的。

UPDATED to refresh all the external resources (images, JavaScript, CSS, etc.)

Put this in file named HardRefresh.js:

  function hardRefresh() {
    const t = parseInt(Date.now() / 10000); //10s tics
    const x = localStorage.getItem("t");
    localStorage.setItem("t", t);

    if (x != t) location.reload(true) //force page refresh from server
    else { //refreshed from server within 10s
      const a = document.querySelectorAll("a, link, script, img")
      var n = a.length
      while(n--) {
        var tag = a[n]
        var url = new URL(tag.href || tag.src);
        url.searchParams.set('r', t.toString());
        tag.href = url.toString(); //a, link, ...
        tag.src = tag.href; //rerun script, refresh img
      }
    }
  }

  window.addEventListener("DOMContentLoaded", hardRefresh);
  window.addEventListener("deviceorientation", hardRefresh, true);

This code do a fully controled forced hard refresh for every visitor, so that any update will show up without a cashing problem.

Duplicated DOM rendering is not a performance issue, because the first render is from cache and it stops rendering in <script src="js/HardRefresh.js"> where it reload a page from server. When it run a refreshed page it also refresh urls in page.

The last refresh time x is stored in localStorage. It is compared with the current time t to refresh within 10 seconds. Assuming a load from server not take more than 10 sec we manage to stop a page refresh loop, so do not have it less than 10s.

For a visitor of page the x != t is true since long time ago or first visit; that will get page from server. Then diff is less than 10s and x == t, that will make the else part add query strings to href and src having sources to refresh.

The refresh() function can be called by a button or other conditioned ways. Full control is managed by refining exclusion and inclusion of urls in your code.

小猫一只 2024-08-25 15:23:25

对于 Angular 用户,如此处所示,您可以执行以下操作:

<form [action]="myAppURL" method="POST" #refreshForm></form>
import { Component, OnInit, ViewChild } from '@angular/core';

@Component({
  // ...
})
export class FooComponent {
  @ViewChild('refreshForm', { static: false }) refreshForm: ElementRef<HTMLFormElement>;

  forceReload() {
    this.refreshForm.nativeElement.submit();
  }
}

解释:Angular

Location:reload(),Location.reload() 方法会重新加载当前 URL,就像刷新按钮一样。仅使用 location.reload();如果您想执行强制重新加载(例如使用 Ctrl + F5 完成)以便从服务器而不是从浏览器缓存重新加载所有资源,这不是一个解决方案。此问题的解决方案是对当前位置执行 POST 请求,因为这总是使浏览器重新加载所有内容。

不使用 Angular

显然,“通过帖子获取文件确实会清除缓存的文件,并且它似乎可以在任何浏览器中工作”,

因此使用“he fetch api with POST”也应该可以工作

For angular users and as found here, you can do the following:

<form [action]="myAppURL" method="POST" #refreshForm></form>
import { Component, OnInit, ViewChild } from '@angular/core';

@Component({
  // ...
})
export class FooComponent {
  @ViewChild('refreshForm', { static: false }) refreshForm: ElementRef<HTMLFormElement>;

  forceReload() {
    this.refreshForm.nativeElement.submit();
  }
}

explanation: Angular

Location: reload(), The Location.reload() method reloads the current URL, like the Refresh button. Using only location.reload(); is not a solution if you want to perform a force-reload (as done with e.g. Ctrl + F5) in order to reload all resources from the server and not from the browser cache. The solution to this issue is, to execute a POST request to the current location as this always makes the browser to reload everything.

Not using Angular

Apparently, "Fetching the file by post does clear the cached file and it seems to work in any browser"

So using "he fetch api with POST" should also work

陌生 2024-08-25 15:23:25

接受的答案 location.reload(true); 不起作用。原因如下(直接取自 MDN 页面):

注意:Firefox 支持 location.reload() 的非标准 forceGet 布尔参数,以告诉 Firefox 绕过其缓存并强制重新加载当前文档。但是,在所有其他浏览器中,您在 location.reload() 调用中指定的任何参数都将被忽略,并且不会产生任何影响。

不过,您可能会在现有代码中遇到 location.reload(true) 的实例,这些代码是假设强制重新加载效果发生在所有浏览器中而编写的。 GitHub“location.reload(true)”搜索返回数十万结果。所以有很多现有的代码都包含它。

它的历史是:Netscape Navigator 的某些版本添加了对它的支持,显然最终在 Firefox 中得到了支持。 W3C Web API 工作组一度考虑将其添加到 location.reload() 规范中。然而,它从未被实际添加。

因此,布尔参数不是当前 location.reload() 规范的一部分,而且事实上从未成为任何已发布的 location.reload() 规范的一部分。

来源:https://developer.mozilla.org/en- US/docs/Web/API/Location/reload

那么,如何强制硬刷新呢?两个想法:

  1. 使用查询字符串,如本线程中多个其他答案中建议/解释/演示的那样;

  2. 请求充斥着 W3C。
    https://www.w3.org/Consortium/contact

(有建议 # 2 几年前就被广泛采用,我们几年前就可以停止使用查询字符串 hack。)

The accepted answer location.reload(true); DOES NOT WORK. Here's why (taken directly from the MDN page):

Note: Firefox supports a non-standard forceGet boolean parameter for location.reload(), to tell Firefox to bypass its cache and force-reload the current document. However, in all other browsers, any parameter you specify in a location.reload() call will be ignored and have no effect of any kind.

You may, though, come across instances of location.reload(true) in existing code that was written with the assumption the force-reload effect occurs in all browsers. A GitHub "location.reload(true)" search returns several hundred thousand results. So there's a lot of existing code which has it.

The history of it is: some version of Netscape Navigator added support for it, which apparently eventually got picked up in Firefox. And at one point the W3C Web APIs Working Group took up an issue to consider adding it to the specification for location.reload(). However, it was never actually added.

So a boolean parameter is not part of the current specification for location.reload() — and in fact has never been part of any specification for location.reload() ever published.

Source: https://developer.mozilla.org/en-US/docs/Web/API/Location/reload

So, how to force a hard refresh? Two ideas:

  1. Use query strings, as suggested/explained/demoed in multiple other answers in this thread;

  2. Flood the W3C with requests.
    https://www.w3.org/Consortium/contact

(Had suggestion #2 been widely adopted years ago, we could have stopped using the query string hack years ago.)

漆黑的白昼 2024-08-25 15:23:25

location.reload(true) 已被弃用,因此没有直接的硬重新加载选项,但我们仍然可以手动清除缓存,然后重新加载。
请改用此自定义函数。

export const clearCache =  (reloadAfterClear = true) => {
    if('caches' in window){
        caches.keys().then((names) => {
            names.forEach(async (name) => {
                await caches.delete(name)
            })
        })

        if(reloadAfterClear)
            window.location.reload()
    }
}

如果您不想立即刷新而只是清除缓存,请使用 clearCache(false)

希望它能有所帮助,因为上述选项都不适合我。

The location.reload(true) is deprecated so there is no direct option to hard reload but we can still manually clear the cache and then reload.
Use this custom function instead.

export const clearCache =  (reloadAfterClear = true) => {
    if('caches' in window){
        caches.keys().then((names) => {
            names.forEach(async (name) => {
                await caches.delete(name)
            })
        })

        if(reloadAfterClear)
            window.location.reload()
    }
}

If you don't want to refresh immidiately and just clear the cache, use clearCache(false)

Hope it helps as none of the above options worked for me.

彩虹直至黑白 2024-08-25 15:23:25

我发现的最可靠的方法是通过向查询字符串添加值来使用 Chache Buster。

这是我使用的通用例程:

    function reloadUrl() {

        // cache busting: Reliable but modifies URL
        var queryParams = new URLSearchParams(window.location.search);
        queryParams.set("lr", new Date().getTime());        
        var query = queryParams.toString();                
        window.location.search = query;  // navigates
    }

调用此例程将产生类似以下内容:

https://somesite.com/page?lr=1665958485293

重新加载后。

这可以强制每次重新加载,但需要注意的是 URL 会发生变化。在大多数应用程序中,这并不重要,但如果服务器依赖于特定参数,这可能会导致潜在的副作用。

The most reliable way I've found is to use a chache buster by adding a value to the querystring.

Here's a generic routine that I use:

    function reloadUrl() {

        // cache busting: Reliable but modifies URL
        var queryParams = new URLSearchParams(window.location.search);
        queryParams.set("lr", new Date().getTime());        
        var query = queryParams.toString();                
        window.location.search = query;  // navigates
    }

Calling this will produce something like this:

https://somesite.com/page?lr=1665958485293

after a reload.

This works to force reload every time, but the caveat is that the URL changes. In most applications this won't matter, but if the server relies on specific parameters this can cause potential side effects.

彼岸花ソ最美的依靠 2024-08-25 15:23:24

⚠️ 此解决方案不适用于所有浏览器。 location.reload() 的 MDN 页面


<块引用>

注意:Firefox 支持 location.reload() 的非标准 forceGet 布尔参数,以告诉 Firefox 绕过其缓存并强制重新加载当前文档。但是,在所有其他浏览器中,您在 location.reload() 调用中指定的任何参数都将被忽略,并且不会产生任何效果。


尝试:

location.reload(true);

当此方法接收 true 值作为参数时,它将导致页面始终从服务器重新加载。如果为 false 或未指定,浏览器可能会从缓存中重新加载页面。

详细信息:

⚠️ This solution won't work on all browsers. MDN page for location.reload():

Note: Firefox supports a non-standard forceGet boolean parameter for location.reload(), to tell Firefox to bypass its cache and force-reload the current document. However, in all other browsers, any parameter you specify in a location.reload() call will be ignored and have no effect of any kind.

Try:

location.reload(true);

When this method receives a true value as argument, it will cause the page to always be reloaded from the server. If it is false or not specified, the browser may reload the page from its cache.

More info:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文