Next.js API路由加载Public目录自定义字体及Sharp转SVG报错求助
在Next.js API路由中使用Sharp加载自定义字体并解决Fontconfig错误
加载自定义字体(替代localFont方案)
localFont仅适用于React客户端组件,API路由属于Node.js环境,需要直接通过文件系统读取字体并嵌入SVG:
- 存放字体文件:将自定义字体(如
CustomFont.ttf)放在项目的public/fonts/目录下。 - 读取字体并转Base64:在API路由中通过
fs读取字体文件,转成Base64格式嵌入SVG的@font-face中(避免路径依赖问题)。 - 构造带字体的SVG:在SVG的
<style>标签中定义自定义字体,确保文本使用该字体。
示例API路由代码(pages/api/generate-png.js):
import sharp from 'sharp'; import fs from 'fs/promises'; import path from 'path'; export default async function handler(req, res) { // 处理Fontconfig缓存目录问题 process.env.XDG_CACHE_HOME = '/tmp'; // 读取public目录下的自定义字体 const fontPath = path.join(process.cwd(), 'public/fonts/CustomFont.ttf'); const fontBuffer = await fs.readFile(fontPath); const fontBase64 = fontBuffer.toString('base64'); // 构造包含自定义字体的SVG const svgContent = ` <svg width="600" height="300" xmlns="http://www.w3.org/2000/svg"> <style> @font-face { font-family: 'CustomFont'; src: url(data:font/ttf;base64,${fontBase64}); font-weight: normal; font-style: normal; } .custom-text { font-family: 'CustomFont', sans-serif; font-size: 56px; fill: #2d3748; text-anchor: middle; } </style> <text x="50%" y="50%" dy=".3em" class="custom-text">自定义字体测试文本</text> </svg> `; // Sharp将SVG转为PNG const pngBuffer = await sharp(Buffer.from(svgContent)) .png() .toBuffer(); // 返回PNG响应 res.setHeader('Content-Type', 'image/png'); res.send(pngBuffer); }
解决Fontconfig error: No writable cache directories
Vercel的函数执行环境默认没有可写的Fontconfig缓存目录,通过以下两种方式解决:
- 代码内设置环境变量:在API路由开头添加
process.env.XDG_CACHE_HOME = '/tmp';(Vercel的/tmp目录是可写的)。 - Vercel控制台设置环境变量:在项目的Vercel控制台中添加环境变量
XDG_CACHE_HOME=/tmp,无需修改代码。
注意事项
- 若字体文件较大,Base64会增加SVG体积,可改用绝对路径引用(确保Sharp能通过
process.cwd()拼接的路径访问到字体文件)。 - 确保字体格式符合要求(如TTF、OTF),Sharp支持常见字体格式。
内容的提问来源于stack exchange,提问作者Reuben Drummond
相关产品推荐
相关产品推荐

