繁体   English   中英

如何使用服务人员处理 index.html 文件的缓存?

[英]How to handle caching of index.html file with service worker?

我目前正在使用create-react-app默认服务工作者开发一个渐进式 web 应用程序。

在发布我们的 javascript 块之一的新版本时,我遇到了破坏缓存的问题。

在构建时,output javascript 文件使用contenthash来确保当 JS 文件中的内容发生变化时,文件名也会发生变化。 在没有服务工作者的情况下运行时,这成功地破坏了缓存。

但是,当使用create-react-app service worker 时,包括我的index.html文件在内的所有 static 资产都会被缓存。 这意味着旧index.html正在提供给用户,其中包含一个<script>标记到我的旧缓存 javascript 文件,而不是具有更新contenthash的新文件。

我已经弹出并修改了 webpack.config.js WorkboxWebpackPlugin以排除我的 index.html 文件:

 new WorkboxWebpackPlugin.GenerateSW({
      clientsClaim: true,
      exclude: [/\.map$/, /asset-manifest\.json$/, /index.html/],
      importWorkboxFrom: "cdn",
      navigateFallbackBlacklist: [
          // Exclude URLs starting with /_, as they're likely an API call
             new RegExp("^/_"),
          // Exclude URLs containing a dot, as they're likely a resource in
          // public/ and not a SPA route
            new RegExp("/[^/]+\\.[^/]+$")
          ]
        }),

这似乎适当地停止了我的索引文件的缓存,允许它在其脚本标记中包含更新的main.[contenthash].js 但是,现在我知道我的 PWA 将无法脱机工作,因为 index.html 文件不是由 service worker 提供服务,也不会通过脱机连接提供服务。

处理这个问题的最佳方法是什么? 完全离线访问不是必需的,但会很好,并且想知道其他开发人员如何处理他们的索引文件的服务工作者缓存的“破坏”而不完全删除 index.html 被服务工作者缓存? 是否有更实用的方法来处理 index.html 关于带有内容哈希的标签的这种变化?

谢谢

我在一个应用程序 shell 架构上工作,其中服务人员缓存应用程序 shell 并将其返回给后续请求。 For Cache busting, I versioned the app shell also, like appshell-[hash].html, so next time when hash changes, the service worker will cache and serve the new app shell discarding the old one.

使其工作的一种方法是使用“回退到缓存”缓存策略。 本质上,当请求文档(例如index.html文件)时,您首先尝试通过转发获取请求从网络加载它。 但是,如果获取请求失败(网络不可用),您将从缓存中提供请求。 当然,您还需要更新index.html的缓存副本,每个请求都保留为新副本。

这样,如果网络可用 - 您将始终获得index.html的新版本,如果没有,将从缓存中提供最新的已知版本。

如果您将 create-react-app 与 cra-template-pwa (npx create-react-app my-app --template cra-template-pwa) 一起使用,那么您可以在预缓存时过滤掉 index.html 然后注册 index. html 所以它是网络优先的。

import { NetworkFirst } from 'workbox-strategies'

// precacheAndRoute(self.__WB_MANIFEST)

const toPrecache = self.__WB_MANIFEST.filter(
  (file) => !file.url.includes('index.html'),
)

precacheAndRoute(toPrecache)

registerRoute(
  ({ url }) => url.pathname.includes('index.html'),
  new NetworkFirst(),
)

然后您需要删除将所有导航请求路由到 index.html 的部分

// Set up App Shell-style routing, so that all navigation requests
// are fulfilled with your index.html shell. Learn more at
// https://developers.google.com/web/fundamentals/architecture/app-shell
// const fileExtensionRegexp = new RegExp('/[^/?]+\\.[^/]+$')
// registerRoute(
//   // Return false to exempt requests from being fulfilled by index.html.
//   ({ request, url }) => {
//     // If this isn't a navigation, skip.
//     if (request.mode !== 'navigate') {
//       return false
//     } // If this is a URL that starts with /_, skip.

//     if (url.pathname.startsWith('/_')) {
//       return false
//     } // If this looks like a URL for a resource, because it contains // a file extension, skip.

//     if (url.pathname.match(fileExtensionRegexp)) {
//       return false
//     } // Return true to signal that we want to use the handler.

//     return true
//   },
//   createHandlerBoundToURL(process.env.PUBLIC_URL + '/index.html', true),
// )

service worker 仅在生产环境中启用,例如 npm 运行构建的 output。 建议您不要在开发环境中启用离线优先服务工作者,因为当使用以前缓存的资产并且不包括您在本地所做的最新更改时,这可能会导致挫败感。

从 -https://create-react-app.dev/docs/making-a-progressive-web-app/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM