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

为Storybook添加自定义图标字体后启动失败,求解决方案

自定义字体导致Storybook启动失败,组件库本身正常

我开发了一个可跨应用复用的组件库,原本运行正常,但添加图标用的自定义字体后,Storybook无法启动(组件库及Icon组件本身仍能正常工作)。以下是相关配置及错误信息:

.storybook/main.js 配置

const postcss = require("postcss");

module.exports = {
  stories: ["../src/**/*.stories.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
  addons: [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "@storybook/addon-interactions",
    "@storybook/preset-scss",
    {
       name: "@storybook/addon-postcss",
       options: {
         cssLoaderOptions: {
           importLoaders: 1,
         },
         postcssLoaderOptions: {
           implementation: postcss,
         },
       },
     },
  ],
  framework: "@storybook/react",
  core: {
    builder: "@storybook/builder-webpack5",
  },
};

src/styles/index.scss 导入配置

@import "fonts";
@import "colors";
@import "sizes";
@import "icons/icons";

*,
*::before,
*::after {
  box-sizing: border-box;
}

// etc

src/styles/icons/icons.scss 字体定义

@import "my-icons-variables";
$icomoon-font-family: "my-icons" !default;
$icomoon-font-path: "./fonts" !default;

@font-face {
  font-family: '#{$icomoon-font-family}';
  src: url('#{$icomoon-font-path}/#{$icomoon-font-family}.woff2') format('woff2'),
  url('#{$icomoon-font-path}/#{$icomoon-font-family}.ttf') format('truetype'),
  url('#{$icomoon-font-path}/#{$icomoon-font-family}.woff') format('woff'),
  url('#{$icomoon-font-path}/#{$icomoon-font-family}.svg##{$icomoon-font-family}') format('svg');
  font-weight: normal;
  font-style: normal;
  font-display: block;
}

// etc

字体文件路径:所有图标字体文件存放在src/styles/icons/fonts/*路径下。

启动Storybook时的错误信息

ModuleNotFoundError: Module not found: Error: Can't resolve './fonts/my-icons.woff2' in '/home/victor/dev/design-components/src/components/layout/section'
    at /home/victor/dev/design-components/node_modules/webpack/lib/Compilation.js:2016:28
    at /home/victor/dev/design-components/node_modules/webpack/lib/NormalModuleFactory.js:798:13
    at eval (eval at create (/home/victor/dev/design-components/node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:10:1)
    at /home/victor/dev/design-components/node_modules/webpack/lib/NormalModuleFactory.js:270:22
    at eval (eval at create (/home/victor/dev/design-components/node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:9:1)
    at /home/victor/dev/design-components/node_modules/webpack/lib/NormalModuleFactory.js:434:22
    at /home/victor/dev/design-components/node_modules/webpack/lib/NormalModuleFactory.js:116:11
    at /home/victor/dev/design-components/node_modules/webpack/lib/NormalModuleFactory.js:670:25
    at /home/victor/dev/design-components/node_modules/webpack/lib/NormalModuleFactory.js:855:8
    at /home/victor/dev/design-components/node_modules/webpack/lib/NormalModuleFactory.js:975:5
    at /home/victor/dev/design-components/node_modules/neo-async/async.js:6883:13
    at Array.<anonymous> (/home/victor/dev/design-components/node_modules/webpack/lib/NormalModuleFactory.js:950:14)
    at arrayEachFunc (/home/victor/dev/design-components/node_modules/neo-async/async.js:2517:19)
    at Object.parallel (/home/victor/dev/design-components/node_modules/neo-async/async.js:6858:9)
    at NormalModuleFactory._resolveResourceErrorHints (/home/victor/dev/design-components/node_modules/webpack/lib/NormalModuleFactory.js:873:12)
    at /home/victor/dev/design-components/node_modules/webpack/lib/NormalModuleFactory.js:834:18
    at finishWithoutResolve (/home/victor/dev/design-components/node_modules/enhanced-resolve/lib/Resolver.js:312:11)
    at /home/victor/dev/design-components/node_modules/enhanced-resolve/lib/Resolver.js:386:15
    at /home/victor/dev/design-components/node_modules/enhanced-resolve/lib/Resolver.js:435:5
    at eval (eval at create (/home/victor/dev/design-components/node_modules/enhanced-resolve/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:16:1)
    at /home/victor/dev/design-components/node_modules/enhanced-resolve/lib/Resolver.js:435:5
    at eval (eval at create (/home/victor/dev/design-components/node_modules/enhanced-resolve/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:27:1)
    at /home/victor/dev/design-components/node_modules/enhanced-resolve/lib/DescriptionFilePlugin.js:87:43
    at /home/victor/dev/design-components/node_modules/enhanced-resolve/lib/Resolver.js:435:5
    at eval (eval at create (/home/victor/dev/design-components/node_modules/enhanced-resolve/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:16:1)
    at /home/victor/dev/design-components/node_modules/enhanced-resolve/lib/forEachBail.js:16:12
    at /home/victor/dev/design-components/node_modules/enhanced-resolve/lib/AliasPlugin.js:125:14
    at next (/home/victor/dev/design-components/node_modules/enhanced-resolve/lib/forEachBail.js:14:3)
    at forEachBail (/home/victor/dev/design-components/node_modules/enhanced-resolve/lib/forEachBail.js:24:9)
    at /home/victor/dev/design-components/node_modules/enhanced-resolve/lib/AliasPlugin.js:51:5
    at _next0 (eval at create (/home/victor/dev/design-components/node_modules/enhanced-resolve/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:8:1)
    at eval (eval at create (/home/victor/dev/design-components/node_modules/enhanced-resolve/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:30:1)
    at /home/victor/dev/design-components/node_modules/enhanced-resolve/lib/Resolver.js:435:5
    at eval (eval at create (/home/victor/dev/design-components/node_modules/enhanced-resolve/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:16:1)
    at /home/victor/dev/design-components/node_modules/enhanced-resolve/lib/Resolver.js:435:5
    at eval (eval at create (/home/victor/dev/design-components/node_modules/enhanced-resolve/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:16:1)
    at /home/victor/dev/design-components/node_modules/enhanced-resolve/lib/RootsPlugin.js:37:38
    at _next2 (eval at create (/home/victor/dev/design-components/node_modules/enhanced-resolve/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:8:1)
    at eval (eval at create (/home/victor/dev/design-components/node_modules/enhanced-resolve/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:31:1)
    at /home/victor/dev/design-components/node_modules/enhanced-resolve/lib/ConditionalPlugin.js:40:47
    at _next1 (eval at create (/home/victor/dev/design-components/node_modules/enhanced-resolve/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:23:1)
    at eval (eval at create (/home/victor/dev/design-components/node_modules/enhanced-resolve/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:46:1)
    at /home/victor/dev/design-components/node_modules/enhanced-resolve/lib/ConditionalPlugin.js:40:47
    at _next0 (eval at create (/home/victor/dev/design-components/node_modules/enhanced-resolve/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:38:1)
    at eval (eval at create (/home/victor/dev/design-components/node_modules/enhanced-resolve/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:60:1)
    at /home/victor/dev/design-components/node_modules/enhanced-resolve/lib/Resolver.js:435:5
    at eval (eval at create (/home/victor/dev/design-components/node_modules/enhanced-resolve/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:27:1)
    at /home/victor/dev/design-components/node_modules/enhanced-resolve/lib/DescriptionFilePlugin.js:87:43
    at /home/victor/dev/design-components/node_modules/enhanced-resolve/lib/Resolver.js:435:5
    at eval (eval at create (/home/victor/dev/design-components/node_modules/enhanced-resolve/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:16:1)
resolve './fonts/my-icons.woff2' in '/home/victor/dev/design-components/src/components/layout/section'
  using description file: /home/victor/dev/design-components/package.json (relative path: ./src/components/layout/section)
    using description file: /home/victor/dev/design-components/package.json (relative path: ./src/components/layout/section/fonts/my-icons.woff2)
      no extension
        /home/victor/dev/design-components/src/components/layout/section/fonts/my-icons.woff2 doesn't exist
      .mjs
        /home/victor/dev/design-components/src/components/layout/section/fonts/my-icons.woff2.mjs doesn't exist
      .js
        /home/victor/dev/design-components/src/components/layout/section/fonts/my-icons.woff2.js doesn't exist
      .jsx
        /home/victor/dev/design-components/src/components/layout/section/fonts/my-icons.woff2.jsx doesn't exist
      .ts
        /home/victor/dev/design-components/src/components/layout/section/fonts/my-icons.woff2.ts doesn't exist
      .tsx
        /home/victor/dev/design-components/src/components/layout/section/fonts/my-icons.woff2.tsx doesn't exist
      .json
        /home/victor/dev/design-components/src/components/layout/section/fonts/my-icons.woff2.json doesn't exist
      .cjs
        /home/victor/dev/design-components/src/components/layout/section/fonts/my-icons.woff2.cjs doesn't exist
      as directory
        /home/victor/dev/design-components/src/components/layout/section/fonts/my-icons.woff2 doesn't exist

(每个组件都会报此错误)

问题

请问是缺少webpack配置,还是导入图标字体的方式有误?

解决方案

问题出在两个方面,以下是修复步骤:

  1. 修正字体相对路径
    组件导入全局样式时,webpack会将字体路径解析为相对于组件文件的路径,而非相对于icons.scss的路径。修改icons.scss中的字体路径变量,使用基于项目根目录的绝对路径:

    // 替换原$icomoon-font-path定义
    $icomoon-font-path: "../src/styles/icons/fonts" !default;
    
  2. 添加Storybook字体文件处理配置
    当前配置未包含字体文件的webpack loader,需要在.storybook/main.js中添加规则,让webpack识别并处理字体资源:

    const postcss = require("postcss");
    
    module.exports = {
      // 保留原有配置
      stories: ["../src/**/*.stories.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
      addons: [/* ...原有addons配置... */],
      framework: "@storybook/react",
      core: { builder: "@storybook/builder-webpack5" },
      // 添加webpackFinal配置
      webpackFinal: async (config) => {
        config.module.rules.push({
          test: /\.(woff|woff2|eot|ttf|otf)$/i,
          type: 'asset/resource',
        });
        return config;
      },
    };
    

完成以上修改后,webpack就能正确解析字体文件路径,Storybook也会将字体资源复制到输出目录,启动即可正常运行。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 21:20:16