如何在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
相关产品推荐
相关产品推荐

