总是回复 index.html

Respond always with index.html

React 应用程序(通常)对所有 URL 使用相同的 index.html,这就是我的服务器响应的内容。

但是,第一个请求永远不会example.com/index.html,例如example.com/example.com/postsexample.com/post/123example.com/contact 等等..

如果我从 Chrome DevTools 打开离线模式,我只会看到默认的无连接页面。

如何始终从缓存中响应 index.html


相关代码:

self.addEventListener('install', function(e) {
    self.skipWaiting()

    e.waitUntil(
        caches.open('v1').then(function(cache) {
            return cache.addAll([
                'index.html',
                'main.js',
                'main.css'
            ])
        })
    )
})

self.addEventListener('fetch', function(e) {
    e.respondWith(
        caches.match(e.request).then(function(match) {
            // If no match in cache, send request
            return match || fetch(e.request)
        })
    )
})

我正在使用 localhost,但我找不到任何关于此问题的重要信息。

这是因为您已明确尝试仅从缓存中打开缓存命中(caches.match(e.request).then...在您的 fetch 侦听器中)。因此它只会匹配您手动添加到缓存中的 URL。

要使用预缓存值响应所有请求,您需要明确查找 index.html 缓存条目,如下所示:

self.addEventListener('fetch', function(e) {
    var indexRequest = new Request('/index.html');

    // route index.html-based URLs to the specific cache directly
    if (shouldRespondWithIndex(e.request.url)) {
        e.respondWith(caches.match(indexRequest))
    } else {
        // other URLs may go through the standard "look for exact match
        // in the cache with network fallback" route
        e.respondWith(
            caches.match(e.request).then(function(match) {
                // If no match in cache, send request
                return match || fetch(e.request)
            }))
    }
})

请注意,对于所有非文档请求,即图像、样式表等,您的 shouldRespondWithIndex 实施应该 return false,否则 Service Worker 会将其替换为 index.html,也是。

您需要更改这部分代码:

caches.match(e.request).then(function(match) {
    // If no match in cache, send request
    return match || fetch(e.request)
})

给returnindex.html给定你想要的条件。您可以在缓存文档中找到更多信息。

https://developer.mozilla.org/en-US/docs/Web/API/Cache

为了响应访问者并避免离线屏幕,您必须决定如何处理的部分是如何检查 event.request 以查看 returning index.html 是否良好,否则即使您不想,也可能 return。你必须使用event.respondWith,手动打开缓存,找到你想要的缓存元素并return它。因此,与其查找 event.request 的匹配项,不如像这样查找 index.html 的匹配项:

  event.respondWith(

    // Opens Cache objects that start with 'font'.
    caches.open(CURRENT_CACHES['font']).then(function(cache) {
      return cache.match('/index.html').then(function(response) {
        if (response) {
          console.log(' Found response in cache:', response);

          return response;
        } 
      }).catch(function(error) {

        // Handles exceptions that arise from match() or fetch().
        console.error('  Error in fetch handler:', error);

        throw error;
      });
    })
  );