You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Next.js中动态加载优化的Google Fonts?

如何根据JSON配置动态加载Next.js的Google Fonts?

我现在用JSON文件来控制Next.js站点要导入的字体。Next.js支持本地导入优化后的Google Fonts,比直接从Google导入性能更好,但这种导入方式好像得提前明确要用到的字体,比如:

import { Inter, Lora, Lato, Abril_Fatface } from 'next/font/google'

我想根据JSON文件里指定的字体名称,动态导入对应的字体加载函数。试过批量导入所有字体:

import * as exports from 'next/font/google'
const inter = exports.Inter({ subsets: ['latin'] })

但报错:"Font loaders can't have namespace imports"。有没有办法不用逐个导入并创建所有字体变量,只加载JSON指定的那一款字体?

当前可行的逐个导入代码如下:

import {
    Inter,
    Lora,
    Abril_Fatface,
    Lato,
    Alegreya_Sans,
    Alegreya_Sans_SC,
    Amatic_SC,
    Anton,
    Artifika,
} from 'next/font/google'

const inter = Inter({ subsets: ['latin'] })

const lato = Lato({ weight: ['300', '400', '700'], style: ['normal', 'italic'], subsets: ['latin'], variable: '--lato' })
const lora = Lora({ subsets: ['latin'], variable: '--lora' })
const abril_flatface = Abril_Fatface({ weight: ['400'], style: ['normal'], subsets: ['latin'], variable: '--abril' })

const alegreya_sans = Alegreya_Sans({ weight: ['300', '400', '700'], subsets: ['latin'] })
const alegreya_sans_sc = Alegreya_Sans_SC({ weight: ['300', '400', '700'], subsets: ['latin'] })
const amatic_sC = Amatic_SC({ weight: ['400', '700'], subsets: ['latin'] })

const anton = Anton({ weight: ['400'], subsets: ['latin'] })
const artifika = Artifika({ weight: ['400'], subsets: ['latin'] })

解决方案

1. 先做字体名称映射

Next.js的next/font/google导出的字体名称是下划线分隔格式(比如Abril_Fatface),但JSON里可能存的是用户友好的名称(比如Abril Fatface),所以先建一个映射文件统一格式:

创建fontMappings.js:

export const fontNameMap = {
  "Inter": "Inter",
  "Lora": "Lora",
  "Lato": "Lato",
  "Abril Fatface": "Abril_Fatface",
  "Alegreya Sans": "Alegreya_Sans",
  "Alegreya Sans SC": "Alegreya_Sans_SC",
  "Amatic SC": "Amatic_SC",
  "Anton": "Anton",
  "Artifika": "Artifika"
}

2. 动态加载指定字体

利用Next.js支持的动态导入特性,避开命名空间导入的限制,只加载JSON指定的字体:

假设你的fontConfig.json配置如下:

{
  "selectedFont": "Abril Fatface",
  "fontOptions": {
    "weight": ["400"],
    "style": ["normal"],
    "subsets": ["latin"],
    "variable": "--abril"
  }
}

在组件/页面中实现动态加载:

import { fontNameMap } from './fontMappings'
import fontConfig from './fontConfig.json'

// 封装字体加载函数
async function loadSelectedFont() {
  const fontExportName = fontNameMap[fontConfig.selectedFont]
  if (!fontExportName) throw new Error('不支持该字体')

  // 动态导入单个字体成员
  const fontModule = await import('next/font/google')
  const fontLoader = fontModule[fontExportName]
  
  return fontLoader(fontConfig.fontOptions)
}

// 在Server Component中直接使用(Client Component可结合useEffect)
export default async function Page() {
  const font = await loadSelectedFont()

  return (
    <main className={font.className}>
      <h1>这是动态加载的字体效果</h1>
    </main>
  )
}

3. 静态生成场景优化

如果是SSG(静态站点生成),可以在getStaticProps中提前加载字体,避免客户端加载延迟:

import { fontNameMap } from './fontMappings'
import fontConfig from './fontConfig.json'

export async function getStaticProps() {
  const fontExportName = fontNameMap[fontConfig.selectedFont]
  const fontModule = await import('next/font/google')
  const fontLoader = fontModule[fontExportName]
  const font = fontLoader(fontConfig.fontOptions)

  return {
    props: {
      fontClass: font.className,
      fontVariable: font.variable
    }
  }
}

export default function Page({ fontClass }) {
  return (
    <main className={fontClass}>
      <h1>静态生成的动态字体</h1>
    </main>
  )
}

关键注意事项

  • 必须避免import * as ...的命名空间导入,这是Next.js字体优化机制的硬性限制,它需要提前明确要打包的字体文件。
  • 动态导入的路径必须是静态可分析的,所以我们通过映射找到导出名称后,直接从next/font/google中提取对应成员。
  • 如果需要支持多字体,只需在JSON中配置字体数组,循环执行加载逻辑即可。

内容的提问来源于stack exchange,提问作者jedwards404

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 03:23:24