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

如何为Storybook 6.5.5版本通过@font-face添加自定义字体?

Storybook自定义字体无法加载的排查与解决

问题描述

尝试了多种为Storybook添加自定义字体的方案均未成功,目前在.storybook目录下配置了以下文件,字体文件存储在src/styles/目录,因已有main.js故未添加方案要求的config.js:

1. webpack.config.js

const path = require('path');

module.exports = async ({ config }) => {
  // fonts
  config.module.rules.push({
    test: /\.(png|woff|woff2|eot|ttf|svg)$/,
    use: [
      {
        loader: 'file-loader',
        options: {
          name: '[name].[ext]',
        },
      },
    ],
    include: path.resolve(__dirname, '../'),
  });

  return config;
};

2. preview.head.html

<style type="text/css">
  @font-face {
    font-family: 'Eina';
    src: url('../src/styles/Eina03-Regular.ttf') format('truetype');
    font-weight: 400;
    font-style: normal;
  }
  @font-face {
    font-family: 'Eina';
    src: url('../src/styles/Eina03-SemiBold.ttf') format('truetype');
    font-weight: 600;
    font-style: normal;
  }
  @font-face {
    font-family: 'Eina';
    src: url('../src/styles/Eina03-Bold.ttf') format('truetype');
    font-weight: 700;
    font-style: normal;
  }
</style>

3. main.js

const path = require('path');

module.exports = {
  stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
  staticDirs: ['../public', '../public/fonts'],
  addons: [
    '@storybook/addon-links',
    '@storybook/addon-essentials',
    '@storybook/addon-interactions',
    {
      name: '@storybook/addon-postcss',
      options: {
        postcssLoaderOptions: {
          implementation: require('postcss'),
        },
      },
    },
  ],
  framework: '@storybook/react',
  core: {
    builder: 'webpack5',
  },
  webpackFinal: async config => {
    config.module.rules.push({
      test: /\.scss$/,
      use: ['style-loader', 'css-loader', 'sass-loader'],
      include: path.resolve(__dirname, '../'),
    });

    return config;
  },
};

解决方案

1. 移除冗余的webpack.config.js

你使用的是Webpack 5,Storybook的main.js中webpackFinal已可处理所有webpack配置,单独的webpack.config.js会导致规则冲突,直接删除该文件,将字体处理规则合并到main.js的webpackFinal中。

2. 适配Webpack5的字体资源规则

Webpack5内置资源模块,无需file-loader,改用asset/resource:
修改main.js的webpackFinal部分:

webpackFinal: async config => {
  // 处理scss
  config.module.rules.push({
    test: /\.scss$/,
    use: ['style-loader', 'css-loader', 'sass-loader'],
    include: path.resolve(__dirname, '../'),
  });

  // 处理字体资源
  config.module.rules.push({
    test: /\.(woff|woff2|eot|ttf|svg)$/i,
    type: 'asset/resource',
    generator: {
      filename: 'fonts/[name][ext]'
    },
    include: path.resolve(__dirname, '../src/styles'),
  });

  return config;
},

3. 修正preview.head.html中的字体路径

Webpack会将字体打包到输出目录的fonts文件夹下,调整路径为相对Storybook预览页面的地址:

<style type="text/css">
  @font-face {
    font-family: 'Eina';
    src: url('./fonts/Eina03-Regular.ttf') format('truetype');
    font-weight: 400;
    font-style: normal;
  }
  @font-face {
    font-family: 'Eina';
    src: url('./fonts/Eina03-SemiBold.ttf') format('truetype');
    font-weight: 600;
    font-style: normal;
  }
  @font-face {
    font-family: 'Eina';
    src: url('./fonts/Eina03-Bold.ttf') format('truetype');
    font-weight: 700;
    font-style: normal;
  }
</style>

4. 全局应用字体

在.storybook/preview.js中引入项目全局样式文件(若有),确保字体在所有Story中生效:

import '../src/styles/global.scss';

全局样式示例:

body {
  font-family: 'Eina', sans-serif;
}

5. 清理缓存并重启Storybook

执行命令清理缓存后重启,避免旧配置干扰:

npx storybook --no-manager-cache

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 05:48:22