PWA app,移动Chrome,强制重新加载js缓存文件

时间:2018-02-17 18:48:43

标签: javascript google-chrome webpack progressive-web-apps

我有PWA应用,我使用Webpack渲染js文件:

{% render_bundle 'app' 'js' %}

在移动Chrome中启动PWA应用后,文件不会更新。 Chrome很可能使用缓存版本。

我尝试删除PWA应用并重新安装,但没有帮助。

之后我手动清除了移动Chrome缓存并刷新了文件,但是,大多数用户都不会这样做,因此我需要另一个不需要最终用户采取任何操作的解决方案。

类似question的答案建议在js文件中添加参数或版本号。

<script type="text/javascript" src="myfile.js?REVISION"></script>

但是,我不知道如何使用Webpack做到这一点?

一个更受欢迎的answer解释说我可以使用hash或chunkhash使用Webpack生成文件名:

output: {
    path: '/',
    filename: '[hash].js',
    chunkFilename: '[chunkhash].js',
},

这个解决方案对我来说不起作用,因为每当有一些chnages时我都无法更改文件的名称。该文件的名称应该保持不变,因为我使用的是django的 collectfast 应用程序。它检查静态文件的md5sum并仅更新那些已更改的文件。

静态js文件的名称应保持不变。同时,我需要一种机制来强制移动Chrome更新已更改的文件。

3 个答案:

答案 0 :(得分:1)

if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('service-worker.js')
        .then(reg => {
            reg.onupdatefound = () => {
                const installingWorker = reg.installing;
                installingWorker.onstatechange = () => {
                    switch (installingWorker.state) {
                        case 'installed':
                            if (navigator.serviceWorker.controller) {
                                // new update available
                                setTimeout(() => document.location.reload(true), 1000);
                                caches.keys().then(keys => {
                                    keys.forEach(key => caches.delete(key));
                                })
                            }
                            break;
                    }
                };
            };
        })
}

答案 1 :(得分:1)

我试图在此处使用Svelte PWA代码做同样的事情: https://github.com/kuhlaid/svelte2/releases/tag/v0.1.6

我求助于运行应用程序构建过程,然后使用“替换文件”插件(请参见rollup.config.js脚本)。如果您在源代码中搜索“ __cVersion__”,您将看到我在何处添加文件修订字符串以尝试强制文件更新(不是本地存储)。

PWA要做的另一件事是,如果您要构建与Workbox之类的服务来在服务工作者中预缓存文件的服务,请确保在用户浏览器中清除CacheStorage。这是您在构建过程中无法执行的操作,因为清除CacheStorage的代码需要在访问浏览器中的应用程序时运行。要清除此缓存,您可以在应用的javascript中插入以下内容:

const l = console.log    
if ('caches' in window) {
  l('CacheStorage is present for this app');
  caches.keys().then(function(cacheArray) {
    l(cacheArray); // just print the list of CacheStorage names to the console
    // for each cache, try and delete it
    cacheArray.forEach(function(cache) {
      caches.delete(cache).then((bool) => {
        l('deleted cache: '+cache); // print the successful deletion to console
      }).catch((err) => {l(err)});
    });
  });
}

这一切都很好,但是这引出了下一个问题,即您如何仅对新代码构建/更新执行一次ONCE?好吧,可能可以将“代码版本”变量添加到您的javascript中,例如:

const codeVersion = __cVersion__;

然后在代码构建/汇总期间,将__cVersion__动态替换为新版本字符串(例如v0.112),并将此codeVersion值存储到应用程序的localStorage中。然后,每次构建时,您都将首先检查localStorage中版本字符串的更改,如果更改了,请运行代码以删除该应用程序的CacheStorage(如上所述)。我的PWA代码的此版本处理以下情况: https://github.com/kuhlaid/svelte2/releases/tag/v0.1.7

为最终用户自动清除缓存是开发人员应事先了解的PWA(或任何应用程序)的复杂性之一。没有人喜欢这样的应用程序,开发人员会告诉您该应用程序在每次推送代码更新时都需要手动清除浏览器缓存。

答案 2 :(得分:0)

您可以尝试将其中之一放入html中, 这将迫使缓存过期。

<meta http-equiv="cache-control" content="max-age=0" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="expires" content="0" />
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
<meta http-equiv="pragma" content="no-cache" />