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

NX工作区中如何在MUI主题库正确使用@next/font

问题

我在NX工作区中使用Next.js、MUI组件库,通过@next/font加载谷歌字体。我创建了一个shared-ui库来导出全局统一的MUI主题,主题本身没问题,但字体配置时出现以下错误:

Font loaders cannot be used from within node_modules.
Location: ..\..\libs\shared\ui\src\lib\shared-ui.tsx 

该库的project.json配置如下:

{
  "name": "shared-ui",
  "$schema": "../../../node_modules/nx/schemas/project-schema.json",
  "sourceRoot": "libs/shared/ui/src",
  "projectType": "library",
  "tags": [],
  "targets": {
    "lint": {
      "executor": "@nrwl/linter:eslint",
      "outputs": ["{options.outputFile}"],
      "options": {
        "lintFilePatterns": ["libs/shared/ui/**/*.{ts,tsx,js,jsx}"]
      }
    },
    "test": {
      "executor": "@nrwl/jest:jest",
      "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
      "options": {
        "jestConfig": "libs/shared/ui/jest.config.ts",
        "passWithNoTests": true
      }
    }
  }
}

请问如何在NX工作区中正确结合MUI与@next/font?


解决方案

问题根源是@next/font的加载逻辑仅允许在Next.js应用层执行——NX会将library编译后放入node_modules目录,触发了Next.js的加载限制。按以下步骤调整即可解决:

  1. 将字体初始化移至Next.js应用根目录
    在你的Next.js应用(如apps/your-app)中创建字体配置文件,比如src/config/fonts.ts,在这里完成谷歌字体的加载:

    import { Inter } from '@next/font/google';
    
    // 根据需求配置字重、子集等参数
    export const interFont = Inter({
      subsets: ['latin'],
      weight: ['300', '400', '500', '700'],
      variable: '--font-inter',
    });
    
  2. 修改shared-ui库的主题文件,依赖外部字体变量
    在shared-ui库的主题文件中,不再直接初始化字体,而是通过CSS变量引用应用层传入的字体:

    import { createTheme } from '@mui/material/styles';
    
    export const createAppTheme = () => {
      return createTheme({
        typography: {
          fontFamily: 'var(--font-inter)',
        },
        // 其他主题配置项...
      });
    };
    
  3. 在Next.js根组件中注入字体与主题
    在apps/your-app/src/app/layout.tsx(或_app.tsx,取决于Next.js版本)中,引入字体和主题,将字体className注入根元素,同时挂载MUI的ThemeProvider:

    import { interFont } from './config/fonts';
    import { createAppTheme } from '@your-workspace/shared-ui';
    import { ThemeProvider } from '@mui/material/styles';
    import CssBaseline from '@mui/material/CssBaseline';
    
    const theme = createAppTheme();
    
    export default function RootLayout({
      children,
    }: {
      children: React.ReactNode;
    }) {
      return (
        <html lang="en" className={interFont.className}>
          <body className={interFont.className}>
            <ThemeProvider theme={theme}>
              <CssBaseline />
              {children}
            </ThemeProvider>
          </body>
        </html>
      );
    }
    
  4. (可选)优化NX库的构建配置
    为避免@next/font被打包进library,可在shared-ui的project.json中添加外部依赖配置:

    "targets": {
      // 保留原有targets...
      "build": {
        "executor": "@nrwl/js:tsc",
        "outputs": ["{options.outputPath}"],
        "options": {
          "outputPath": "dist/libs/shared/ui",
          "tsConfig": "libs/shared/ui/tsconfig.lib.json",
          "packageJson": "libs/shared/ui/package.json",
          "main": "libs/shared/ui/src/index.ts",
          "assets": ["libs/shared/ui/*.md"],
          "externalDependencies": ["@next/font"]
        }
      }
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 20:50:31