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

Next.js生产构建时如何保留UI库中的字体引用?

问题背景

我们团队正在开发一个Next.js应用,依赖另一团队提供的共享UI库(the-ui-library)。该库通过CSS的@font-face定义了Roboto字体:

@font-face {
  font-family: 'Roboto';
  src: url('./Roboto/Roboto-VariableFont_wdth,wght.woff2') format('woff2'),
    url('./Roboto/Roboto-VariableFont_wdth,wght.ttf') format('truetype');
  font-weight: 100 300 400 500 700 900;
  font-style: normal;
  font-display: swap;
}

本地运行时字体显示正常,但构建部署到服务器后字体无法加载:字体文件存在于Next.js构建产物中,但@font-face规则未被包含;组件仍引用该字体,但浏览器因无来源引用,不会发起加载请求,控制台无相关报错,网络请求中也无字体加载记录。

当前未使用Next.js的SSR功能,简化后的Next.js配置如下:

/**
 * @type {import('next').NextConfig}
 */

const nextConfig = {
    reactStrictMode: true,
    distDir: 'build',
    output: 'export',
    trailingSlash: true,
    assetPrefix: process.env.NODE_ENV === 'development' ? '' : '/cdn',
    transpilePackages: [
        'redacted-1',
        'redacted-2',
        'the-ui-library',
    ],
    eslint: {
        dirs: [
            'contexts',
            'components',
            'hooks',
            'models',
            'pages',
            'routes',
            'styles',
            'utils',
            '__tests__',
        ],
    },
    images: {
        unoptimized: true,
    },
    webpack: (config) => {
        // 无关内部代码已移除
        return config;
    },
};

export default nextConfig;
解决建议
  • 检查UI库的CSS打包配置
    确认the-ui-library的package.json中是否指定了style字段,指向库的核心CSS文件。如果未指定,Next.js可能无法自动识别并处理库中的CSS规则,导致@font-face丢失。添加该字段后重新构建测试:

    // the-ui-library/package.json
    {
      "style": "dist/styles.css" // 替换为实际CSS文件路径
    }
    
  • 调整Webpack字体与CSS解析规则
    在Next.js的webpack配置中添加字体文件的处理规则,并确保CSS中的相对字体路径被正确解析:

    const path = require('path');
    
    const nextConfig = {
        // 其他配置...
        webpack: (config) => {
            // 处理woff2/ttf字体文件,输出到指定目录
            config.module.rules.push({
                test: /\.(woff2|ttf)$/,
                type: 'asset/resource',
                generator: {
                    filename: 'fonts/[name].[hash][ext]'
                }
            });
    
            // 解析CSS中指向UI库字体的相对路径
            config.module.rules.forEach(rule => {
                if (rule.test?.toString().includes('css')) {
                    rule.resolve = {
                        alias: {
                            './Roboto': path.resolve(__dirname, 'node_modules/the-ui-library/path/to/Roboto')
                        }
                    };
                }
            });
    
            return config;
        },
    };
    

    注意将path/to/Roboto替换为UI库中字体文件的实际存放路径。

  • 手动导入UI库CSS
    在Next.js的全局CSS文件(如styles/globals.css)中手动导入UI库的CSS,确保构建时该文件被纳入产物:

    @import 'the-ui-library/dist/styles.css';
    

    需确认UI库的dist目录下存在对应CSS文件,路径无误。

  • 验证assetPrefix对路径的影响
    由于设置了assetPrefix: '/cdn',需确保字体路径最终会带上该前缀。可通过修改webpack的publicPath配置实现:

    const nextConfig = {
        // 其他配置...
        webpack: (config) => {
            config.output.publicPath = process.env.NODE_ENV === 'development' ? '' : '/cdn/';
            return config;
        },
    };
    
  • 手动复制字体到公共目录
    如果静态导出逻辑未自动收集node_modules中的字体,可手动将UI库的字体文件复制到Next.js的public/fonts目录,然后在全局CSS中重新定义@font-face:

    @font-face {
      font-family: 'Roboto';
      src: url('/cdn/fonts/Roboto-VariableFont_wdth,wght.woff2') format('woff2'),
           url('/cdn/fonts/Roboto-VariableFont_wdth,wght.ttf') format('truetype');
      font-weight: 100 900;
      font-style: normal;
      font-display: swap;
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 04:05:01