Firebase托管:如何防止缓存SPA的index.html

zev*_*vdg 21 cache-control firebase single-page-application firebase-hosting

我在firebase上托管SPA,几乎所有路径都被重写index.html.我正在使用基于webpack hash的缓存清除,所以我想总是阻止缓存我的index.html而不是任何其他文件.我发现这样做非常困难.具体来说,我的文件布局如下所示

/
??? index.html
??? login.html
??? js
?   ??? login.ba22ef2579d744b26c65.bundle.js
?   ??? main.6d0ef60e45ae7a11063c.bundle.js
??? public
    ??? favicon-16x16.ico
Run Code Online (Sandbox Code Playgroud)

"sources": "index.html"在从文档中读到这个引用之前,我开始天真.

无论使用glob表示法的任何重写规则如何,每个定义都必须具有与原始请求路径匹配的源键.

好的,所以不是一个简单的glob指定我想要这些头文件的文件,我想我需要一个路径.由于大多数路径重定向到index.html,我需要一个glob,它排除了我不想放置这些头的所有路径.

作为参考,我的firebase.json托管部分如下所示:

{
  "hosting": {
    "public": "dist",
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ],
    "cleanUrls": true,
    "trailingSlash": false,
    "headers": [
      {
        "source": <<<WHAT-GOES-HERE?>>>,
        "headers": [
          {
            "key": "Cache-Control",
            "value": "no-cache, no-store, must-revalidate"
          },
          {
            "key": "Pragma",
            "value": "no-cache"
          },
          {
            "key": "Expires",
            "value": "0"
          }
        ]
      }
    ]
  }
}
Run Code Online (Sandbox Code Playgroud)

因此,提供一些重定向到index.html并且不应该缓存的示例

mysite.com  
mysite.com/  
mysite.com/foo/bar/baz  
mysite.com/index.html 
Run Code Online (Sandbox Code Playgroud)

注意:如果最后一个被缓存,我可以活下去,因为它没有在实践中使用.

并且不会重定向到index.html并且不应该缓存的东西

**/*.* (ideally excluding index.html)
mysite.com/login  
Run Code Online (Sandbox Code Playgroud)

我自己最接近的是**/!(login|*.*)哪种适用于上面列出的几乎所有内容,但莫名其妙地无法使用mysite.commysite.com/.这两个页面没有匹配这个全局,我无法弄清楚原因.

Gij*_*ese 42

这是我正在使用的配置.逻辑是对所有静态文件使用缓存images, css, js等.对于所有其他,即将缓存"source": "/**"设置为无缓存.因此,对于所有其他文件,可能不会应用example.com,example.com/index.html,example.com/about-us,example.com/about-us.html缓存.

{
  "hosting": {
    "public": "dist",
    "headers": [
      {
        "source": "/**",
        "headers": [
          {
            "key": "Cache-Control",
            "value": "no-cache, no-store, must-revalidate"
          }
        ]
      },
      {
        "source":
          "**/*.@(jpg|jpeg|gif|png|svg|webp|js|css|eot|otf|ttf|ttc|woff|woff2|font.css)",
        "headers": [
          {
            "key": "Cache-Control",
            "value": "max-age=604800"
          }
        ]
      }
    ],
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"]
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 更新:回答我自己的问题(很想听听这是一个好主意还是坏主意)-使用 Cache-Control 值:`max-age=0, s-maxage=604800` 似乎得到了我想要的即时行为客户端更新新页面内容,但仍在 CDN 级别进行缓存 (3认同)
  • 我发现使用这种方法,即使将硬刷新与硬刷新进行比较,它也会使 CDN 的 index.html 页面加载时间增加 300-400 毫秒(就像 CDN 本身根本停止缓存它一样)。有没有什么办法可以两全其美,在文件更改时使缓存失效,始终让客户端从 CDN 获取最新内容? (2认同)

jul*_*ard 5

如果您的应用程序还包含服务工作者,请谨慎对待配置(我们在 firebase 组织内升级了 P1 问题,这就是我们发现的)。您需要确保 Service Worker 不被缓存,并且 Firebase 托管使用“最后的规则获胜”来工作,因此您需要确保您的 Service Worker 规则是最后的。更喜欢这样的东西:

{
  "hosting": {
    "public": "dist",
    "headers": [
      {
        "source":
          "**/*.@(jpg|jpeg|gif|png|svg|webp|js|css|eot|otf|ttf|ttc|woff|woff2|font.css)",
        "headers": [
          {
            "key": "Cache-Control",
            "value": "max-age=604800"
          }
        ]
      },
      {
        "source": "/**",
        "headers": [
          {
            "key": "Cache-Control",
            "value": "no-cache, no-store, must-revalidate"
          }
        ]
      },
      {
        "source": "/service-worker.js",
        "headers": [
          {
            "key": "Cache-Control",
            "value": "no-cache, no-store, must-revalidate"
          }
        ]
      }
    ],
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"]
  }
}
Run Code Online (Sandbox Code Playgroud)

特别是因为你的 Service Worker 可能会进行预缓存,所以即使你的 index.html 不会在 CDN 级别缓存,并且 HTTP 请求将获得一个新副本,但通过 Service Worker 的预缓存,你仍然可以提供服务index.html 的旧副本