设置 service worker 只排除某些 url

Setting service worker to exclude certain urls only

我使用 create react 构建了一个应用程序,默认情况下包含一个 service worker。我希望应用程序在有人输入给定的 url 时成为 运行,除非他们转到 /blog/,它提供一组静态内容。我在应用程序中使用反应路由器来捕获不同的 urls.

我有 nginx 设置来服务 /blog/ 如果有人访问 /blog/ 没有先访问反应应用程序,它工作正常。但是,因为 service worker 的作用域是 ./,任何时候有人访问除 /blog/ 之外的任何 url,应用程序都会加载 service worker。从那时起,service worker 绕过与服务器的连接并 /blog/ 加载反应应用程序而不是静态内容。

有没有办法让 Service Worker 在除 /blog/ 之外的所有 url 上加载?

因此,考虑到您还没有发布任何与 service worker 相关的代码,您可以考虑在 fetch

的代码块中添加一个简单的 if 条件

此代码块应该已经存在于您的服务中worker.Just添加条件

self.addEventListener( 'fetch', function ( event ) {

    if ( event.request.url.match( '^.*(\/blog\/).*$' ) ) {
        return false;
    }
     // OR

    if ( event.request.url.indexOf( '/blog/' ) !== -1 ) {
        return false;
    }
    //    **** rest of your service worker code ****

注意您可以使用正则表达式或原型方法indexOf。 随心所欲。

以上将指示您的服务人员,当 url 匹配 /blog/

时什么也不做

黑名单URL的另一种方法,即当您使用Workbox can be achieved with workbox.routing.registerNavigationRoute时,将它们从缓存中排除:

workbox.routing.registerNavigationRoute("/index.html", {
  blacklist: [/^\/api/,/^\/admin/],
});

上面的示例针对 SPA 演示了这一点,其中所有路由都被缓存并映射到 index.html,但以 /api 或 [=14= 开头的任何 URL 除外].

尝试使用 sw-precache library 覆盖当前 service-worker.js 文件,即 运行 缓存策略。最重要的部分是设置配置文件(我将在下面粘贴我与 create-react-app 一起使用的配置文件)。

  1. 安装yarn sw-precache
  2. 创建并指定指示哪些 URL 不缓存的配置文件
  3. 修改构建脚本命令以确保sw-precache运行并覆盖构建输出目录中的默认service-worker.js文件

我将我的配置文件命名为 sw-precache-config.js 并在 package.json[= 的构建脚本命令中指定了它33=]。该文件的内容如下。需要特别注意的部分是runtimeCachingkey/option。 "build": "NODE_ENV=development react-scripts build && sw-precache --config=sw-precache-config.js"

配置文件:sw-precache-config.js

module.exports = {
    staticFileGlobs: [
        'build/*.html',
        'build/manifest.json',
        'build/static/**/!(*map*)',
    ],
    staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/],
    swFilePath: './build/service-worker.js',
    stripPrefix: 'build/',
    runtimeCaching: [
        {
            urlPattern: /dont_cache_me1/,
            handler: 'networkOnly'
        }, {
            urlPattern: /dont_cache_me2/,
            handler: 'networkOnly'
        }
    ]
}

以下是最新 CRA 版本中为我们工作的内容:

// serviceWorker.js

window.addEventListener('load', () => {
  if (isAdminRoute()) {
    console.info('unregistering service worker for admin route')
    unregister()
    console.info('reloading')
    window.location.reload()
    return false
  }

我们从服务器工作者中排除 /admin 下的所有路由,因为我们为我们的管理区域使用了不同的应用程序。您当然可以根据自己的喜好更改它,这是我们在文件底部的功能:

function isAdminRoute() {
  return window.location.pathname.startsWith('/admin')
}

如果你正在使用或愿意使用customize-cra,解决方案相当straight-forward。

将此放入您的 config-overrides.js:

const { adjustWorkbox, override } = require("customize-cra");

module.exports = override(
  adjustWorkbox(wb => 
    Object.assign(wb, {
      navigateFallbackWhitelist: [
        ...(wb.navigateFallbackWhitelist || []),
        /^\/blog(\/.*)?/,
      ],
     })
   )
);

请注意,在最新的 workbox documentation 中,该选项称为 navigateFallbackAllowlist 而不是 navigateFallbackWhitelist。因此,根据您使用的 CRA/workbox 版本,您可能需要更改选项名称。

正则表达式 /^/blog(/.*)?/ 匹配 /blog、/blog/、/blog/abc123 等

以下是您在 2021 年的做法:

import {NavigationRoute, registerRoute} from 'workbox-routing';

const navigationRoute = new NavigationRoute(handler, {
  allowlist: [
    new RegExp('/blog/'),
  ],
  denylist: [
    new RegExp('/blog/restricted/'),
  ],
});
registerRoute(navigationRoute);

https://developers.google.com/web/tools/workbox/modules/workbox-routing#how_to_register_a_navigation_route

更新(新的工作解决方案) 在 Create React App 的最后一个主要版本(版本 4.x.x)中,您可以轻松实现您的自定义 worker-service.js 而无需流血。 customize worker-service

Starting with Create React App 4, you have full control over customizing the logic in this service worker, by creating your own src/service-worker.js file, or customizing the one added by the cra-template-pwa (or cra-template-pwa-typescript) template. You can use additional modules from the Workbox project, add in a push notification library, or remove some of the default caching logic.

如果您当前使用的是旧版本,则必须将您的 React 脚本升级到版本 4。

CRA v4 的工作解决方案

registerRoute-method.

中的匿名函数内将以下代码添加到文件service-worker.js
// If this is a backend URL, skip
if (url.pathname.startsWith("/backend")) {
    return false;
}

为了简化事情,我们可以添加要排除的项目的数组列表,并在获取事件侦听器中添加搜索。

为了完整起见,下面包含和排除方法。

var offlineInclude = [
    '',                // index.html
    'sitecss.css',
    'js/sitejs.js'
];

var offlineExclude = [
    '/networkimages/bigimg.png',   //exclude a file
    '/networkimages/smallimg.png',
    '/admin/'                      //exclude a directory
];

self.addEventListener("install", function(event) {
  console.log('WORKER: install event in progress.');
  event.waitUntil(
    caches
      .open(version + 'fundamentals')
      .then(function(cache) {
        return cache.addAll(offlineInclude);
      })
      .then(function() {
        console.log('WORKER: install completed');
      })
  );
});

self.addEventListener("fetch", function(event) {
  console.log('WORKER: fetch event in progress.');

  if (event.request.method !== 'GET') {
    console.log('WORKER: fetch event ignored.', event.request.method, event.request.url);
    return;
  }

  for (let i = 0; i < offlineExclude.length; i++)
  {
    if (event.request.url.indexOf(offlineExclude[i]) !== -1)
    {
      console.log('WORKER: fetch event ignored. URL in exclude list.', event.request.url);
      return false;
    }
  }