NextJS:从数据库加载字体

NextJS: Loading Font from Database

我正在使用 NextJS 和 Tailwind CSS。

在我的应用程序中,用户可以 select 包含不同配色方案以及预先 select 字体列表的主题。他们可以为应用程序选择他们喜欢的字体。

这些只是 Google 字体。

我不确定根据从数据库收到的字体名称加载字体的最佳方法是什么。我可以从 serverSideProps 中的 database 加载数据,但是我怎样才能在渲染之前加载字体以便没有屏幕闪烁。你能帮忙吗?

更新

截至目前,我已完成以下操作:

  1. tailwind.config.js 中,我用可用的不同字体扩展了主题。

    主题:{ 字体系列: { 间:['Inter', 'sans-serif'], cal: ["Cal Sans", "Inter", "sans-serif"], 华宇:['Arima Madurai','cursive'], opensans:['Open Sans', 'sans-serif'], } }

  2. 我为每种字体创建了一个样式表,它存储在 public 文件夹中的这个位置:

    /fonts/opensans/stylesheet.css

    /fonts/cal/stylesheet.css

    /fonts/inter/stylesheet.css

    /fonts/arima/stylesheet.css

这些样式表包含字体。下面是一个例子:

@font-face {
  font-family: "Cal Sans";
  src: url("CalSans-SemiBold.woff2") format("woff2"),
    url("CalSans-SemiBold.woff") format("woff");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
  1. 在页面上(比如 pages/index.js),我使用 serverSideProps 加载用户的首选项并将其传递给 Layout 组件。此布局组件具有通过 next/head 创建的 head。我们将从服务器收到的字体属性称为 themeFont.

假设用户的偏好是 Cal Sans,并且用户的偏好作为值 cal 存储在数据库中。因此,themeFont 值将是 cal.

在头部,我加载了相关的样式表如下:

<Head>
  <link rel="stylesheet" href={`/fonts/${themeFont}/stylesheet.css`}></link>
</Head>
  1. 这将加载 /fonts/cal/stylesheet.css 和所需的字体。没有加载其他字体。然后我可以在我的组件中使用它 font-cal 因为它已经在 tailwind.config.css
  2. 中定义

它工作正常。我仍然看到闪烁,可能是因为 font-display:swap,也可能是其他原因。但我仍然觉得这不是最佳解决方案,可以通过更好的方式完成。

正在寻求帮助。

两个想法:

  1. Fontsources 维护着 Google 字体的完整存储库作为 NPM 包。你应该可以动态导入你需要的字体,只要安装了相应的npm包。

https://fontsource.org/docs/getting-started

那你知道是什么字体后应该就可以动态导入对应的字体了。不知道这里字体会不会闪烁

await import `@fontsource/${fontName}`;

这假设您知道 fontName 将是一个有效的 Google 字体名称,或者您需要一个 try/catch


  1. 另一种方法是在服务器上获取字体信息(如果您正在使用 Next.js,您可以使用 getServerSideProps 来完成此操作,然后使用自定义 <Head> 元素指向到 fonts.googleapis.com 上相应的 CSS 文件,并在其他内容呈现之前将其作为 <Head> 的一部分加载(或者至少在呈现过程中。)

解决方案 1

你的方向是正确的,你应该使用getServerSideProps<link>标签中设置想要的字体。但是你应该先添加 rel="preload" 属性来加载字体,然后你可以为你的 css.

放置 link
<link rel="preload" href="/fonts/theme-font.woff2" as="font" type="font/woff2" ></link>

元素的 rel 属性的预加载值允许您在 HTML 中声明获取请求,指定您的页面很快将需要的资源,您希望在页面生命周期的早期开始加载这些资源,在浏览器的主要渲染机制启动之前。

然后为避免闪烁使用 fallbackfont-display 属性,它将隐藏文本约 100 毫秒,如果尚未下载字体,将使用备用文本。

@font-face {
  font-family: "Cal Sans";
  font-display: fallback;
  src: url("CalSans-SemiBold.woff2") format("woff2"),
}

您可以为 font-display 使用以下值以用于不同的策略:

  • auto(默认):允许浏览器使用其默认加载方法,这通常类似于块值。
  • block:指示浏览器暂时隐藏文本,直到字体完全下载。更准确地说,浏览器使用不可见的占位符绘制文本,然后在加载后立即将其与自定义字体交换。这也称为“不可见文本的闪光”或 FOIT。
  • swap:指示浏览器使用回退字体显示文本,直到自定义字体完全下载。这也称为“无样式文本的闪光”或 FOUT。
  • fallback:作为 auto 和 swap 值之间的折衷。浏览器将隐藏文本约 100 毫秒,如果尚未下载字体,将使用后备文本。它会在下载后切换到新字体,但只会在很短的切换时间内(大概 3 秒)。
  • optional:与回退一样,此值告诉浏览器最初隐藏文本,然后转换为回退字体,直到自定义字体可用为止。但是,此值还允许浏览器确定是否使用自定义字体,使用用户的连接速度作为决定因素,较慢的连接速度不太可能接收自定义字体。

解决方案 2

作为替代解决方案,您可以将字体嵌入 css 样式中:

@font-face {
  font-family: "Cal Sans";
  font-display: fallback;
  src: url(PASTE-BASE64-HERE) format('woff2')
}

检查此 demo 作为参考,您可以在那里将 woff2 文件转换为 base64。