【问题标题】:How to improve font loading/caching with Vercel/Next.js?如何使用 Vercel/Next.js 改进字体加载/缓存?
【发布时间】:2021-02-27 17:34:16
【问题描述】:

我在网站上使用自定义字体。它有效,但看起来它们缓存的时间不够长,因为我经常得到 FOUT。有时一天多次,在生产中。我希望我可以将字体缓存更长的时间(或其他解决方案),以防止这种情况经常发生。

字体在_document.tsx 中预加载如下:

<link
   rel='preload'
  as='font'
  href='/fonts/Calibre-Regular.woff2'
  type='font/woff2'
  crossOrigin='anonymous'
  />

然后在_app.tsx 中这样:

<script jsx>{`
 @font-face {
  font-family: 'Calibre';
  font-display: swap;
  src: url('/fonts/Calibre-Regular.woff2') format('woff2'),
    url('/fonts/Calibre-Regular.woff') format('woff');
}
`}</script>

我该如何改进呢?或者为字体设置更长的缓存时间? ????????

【问题讨论】:

  • 我似乎遇到了这个问题,因为我的字体在网站第一次交互后重新下载..所以,它下载了多次..这会导致移位。你知道你最终做了什么吗?
  • 我最终将@font-face 导入到外部fonts.css 文件中,我将import "lib/fonts.css" 导入_app.tsx 中。您还可以使用&lt;link rel="preload" href"... 预取字体。我没有做最后一部分,但这个设置效果很好。当它是一个外部 css 文件时,似乎所有东西都比直接在 _app.tsx 中缓存得更好。
  • 我将“@font-face”放在了 global.css 文件中,但我确实将“
  • 是的,它们应该进入_app,您可以通过在文件顶部执行以下操作将它们全局导入:import "lib/main.css";

标签: caching fonts next.js webfonts vercel


【解决方案1】:

如果没有看到完整的示例,我会:

  • 首先确认您的 React 应用程序是服务器渲染的。使用 Next.js,我想是这样,但 link 标记和 script(应该是 style 标记?)应该是初始 HTML 的一部分
  • 检查是否将内联 CSS 更改为 &lt;link /&gt; 标记并分离 CSS 样式,其中仅包含 @font-face 声明。是的,这增加了一个额外的 HTTP 请求,但是 CSS 可能会遵循 Vercel 的静态缓存规则并且在 31 天内不会更改:https://vercel.com/docs/edge-network/caching#static-files(尽管这里不清楚当您重新部署该文件时缓存是否无效,或者当您这样做时任何部署)
  • 决定使用自定义的东西来覆盖 Vercel 的默认缓存设置,并添加 Routes property in your vercel.json file

例如,要将 fonts/ 目录中的所有内容缓存一周(假设新的外部 CSS 文件也在那里),配置将是:

{
  "routes": [
    {
      "src": "/fonts/(.*)",
      "headers": { "cache-control": "s-maxage=604800" },
      "dest": "/fonts/$1"
    }
  ]
}

这是基于文档中的配置示例:https://vercel.com/docs/configuration#routes/headers

希望其中一项或多项对您有所帮助!

【讨论】:

  • 非常感谢您的回复。我还没有时间对此进行全面测试,但我很确定我将能够通过这些技巧解决我的问题。在它到期之前给你赏金,但会用结果回复你。 :)
  • 现在看起来好多了。 :) 我将@font-face 移动到外部.css 文件,并将其作为全局css 文件(未限定范围)导入_app.tsx,如下所示:import lib/main.css。这似乎被正确缓存。 :)
  • 更新后的vercel docs URL:vercel.com/docs/concepts/edge-network/headers
【解决方案2】:

我不太确定 FOUT 是由于字体缓存时间不够长造成的。例如,它们是否尚未加载preload 链接应该导致浏览器请求字体并正常缓存它 - WOFF(2) 文件无论如何都是静态文件。除非特别努力缓存它们,否则它们应该被缓存并且保持缓存。

所以,我会首先检查来自客户端和服务器的那些 WOFF 文件的请求 和响应 标头。究竟是什么被发送 Vercel 层?而且,更重要的是,从服务器发送到缓存的是什么?(我自己放错了足够多的与缓存相关的 pragma,所以我现在总是先检查这些)。

如果没问题,我不会打赌,我会查看实际加载时间并在 FOUT 期间从网站请求瀑布。这可能指向加载序列中的缓存问题或错误(很少见,但我也有这些)。

如果此时没有任何显示,您可以尝试删除 FOUT,否则 - 加载动画、加载延迟或只是 hiding the text

但是我的钱花在了旅程的服务器-Vercel 上,70% 的钱花在了服务器上发送的错误标头上,30% 的钱花在了 Vercel 没有正确反应上。

确定它是缓存还是其他东西的一种肮脏而可怕的方法是让另一台机器以适当的时间间隔从同一网络连续刺探缓存(例如 cron 作业,或者更残酷的,while从商品树莓上的终端使用curlsleep 循环),频率高于FOUT 出现的频率。如果这使 FOUT 消失,那么它可能真的是缓存时间——但坦率地说,我真的很惊讶。

【讨论】:

    猜你喜欢
    • 2022-06-14
    • 1970-01-01
    • 2021-01-03
    • 1970-01-01
    • 1970-01-01
    • 2022-08-13
    • 2021-09-21
    • 2013-12-14
    • 2015-07-07
    相关资源
    最近更新 更多