首页
/ Storybook 的 `no-renderer-packages` 规则:阻止在 Stories 中直接导入渲染器包

Storybook 的 `no-renderer-packages` 规则:阻止在 Stories 中直接导入渲染器包

2026-09-06 18:14:25作者:余洋婵Anita

no-renderer-packages 是 Storybook 官方 ESLint 插件 eslint-plugin-storybook 内置的一条问题级(problem)规则,它禁止在 *.stories.* / *.story.* 文件中直接导入 @storybook/react@storybook/vue3@storybook/web-components 这类渲染器(renderer)基础包,并引导你改而使用与具体构建工具(Vite、Webpack 等)或框架(Next.js、SvelteKit)绑定的框架包(framework package)。本篇文章将基于该规则当前仓库中的文档、源码与测试,讲解规则背景、命中行为、包名替换映射、配置方法及适用范围。

规则背景:为什么不能直接导入渲染器包

Storybook 的包结构分为两层:

  • 渲染器包(renderer packages),如 @storybook/react@storybook/vue3,只提供"把某个 UI 框架渲染进 Storybook 画布"的核心能力,本身不感知构建工具;
  • 框架包(framework packages),如 @storybook/react-vite@storybook/react-webpack5,在渲染器之上绑定具体的构建工具或上层框架,负责解析、加载并针对该构建环境进行优化。

在 Stories 中直接导入渲染器包,通常会绕过框架层提供的集成与优化,导致模块解析、装饰器注入或构建行为与项目实际使用的 Storybook 配置不一致。这条规则因此被纳入插件默认的 recommendedflat/recommended 配置中,随规则文档、规则实现与测试用例一并位于 code/lib/eslint-plugin 目录。

规则报告内容与完整替换映射

当检测到导入语句的包名恰好命中渲染器包清单时,规则会报告 Do not import renderer package "{{rendererPackage}}" directly. Use a framework package instead (e.g. {{suggestions}}).,其中 suggestions 会被拼接成逗号分隔的候选框架包列表。

规则文档只列出了部分映射,而源码 no-renderer-packages.ts 中的 rendererToFrameworks 表更为完整,是判断替换建议的真实依据:

渲染器包 建议的框架包
@storybook/html @storybook/html-vite@storybook/html-webpack5
@storybook/preact @storybook/preact-vite@storybook/preact-webpack5
@storybook/react @storybook/nextjs@storybook/react-vite@storybook/nextjs-vite@storybook/react-webpack5@storybook/react-native-web-vite
@storybook/server @storybook/server-webpack5
@storybook/svelte @storybook/svelte-vite@storybook/svelte-webpack5@storybook/sveltekit
@storybook/vue3 @storybook/vue3-vite@storybook/vue3-webpack5
@storybook/web-components @storybook/web-components-vite@storybook/web-components-webpack5

规则针对的渲染器包类型(RendererPackage)恰好在仓库中有对应的独立渲染器实现目录,例如 code/renderers/reactcode/renderers/vue3code/renderers/sveltecode/renderers/web-components 等,可据此印证"渲染器层"的划分确实存在于项目结构中。

错误与正确示例

以下写法不正确 —— 直接从渲染器包导入:

// Don't import renderer packages directly
import { something } from '@storybook/react';
import { something } from '@storybook/vue3';
import { something } from '@storybook/web-components';

以下写法正确 —— 按构建工具选择对应框架包:

// Do use the appropriate framework package for your build tool
import { something } from '@storybook/react-vite'; // For Vite
import { something } from '@storybook/vue3-vite'; // For Vite
import { something } from '@storybook/web-components-vite'; // For Vite
import { something } from '@storybook/nextjs'; // For Next.js

规则实现:一个纯粹的 ImportDeclaration 检查器

规则实现非常精简,关键逻辑集中在 src/rules/no-renderer-packages.ts

  • 只监听 AST 节点类型 ImportDeclaration
  • 读取 node.source.value 取得被导入的包名字符串;
  • 若该字符串以 in 命中 rendererToFrameworks 映射表,即从表中取出替换建议并 context.report(...)
  • 元信息将规则类型声明为 problem、默认严重度为 error,且 schema: [] 表明该规则不接受任何自定义选项,行为完全由内置映射表决定。

规则通过 create-storybook-rule.ts 中基于 @typescript-eslint/utilsRuleCreator(docsUrl) 构建,文档链接会自动拼接,报错信息指向本规则文档。所有命中与不命中的场景都由测试文件 no-renderer-packages.test.ts 覆盖。

测试验证:哪些导入会命中

测试用例对规则行为给出了明确边界:

视为合法的导入(valid)

  • @storybook/react-vite@storybook/vue3-webpack5@storybook/web-components-vite 等框架包导入;
  • 非 Storybook 的普通导入,例如 import React from 'react'import { something } from 'some-other-package'

判定为错误的导入(invalid)

  • import { something } from '@storybook/react',期望报错并给出完整建议串:@storybook/nextjs, @storybook/react-vite, @storybook/nextjs-vite, @storybook/react-webpack5, @storybook/react-native-web-vite
  • import { something } from '@storybook/vue3',期望建议 @storybook/vue3-vite, @storybook/vue3-webpack5
  • import { something } from '@storybook/web-components',期望建议 @storybook/web-components-vite, @storybook/web-components-webpack5

测试还断言报告节点类型必须为 ImportDeclarationAST_NODE_TYPES.ImportDeclaration),说明规则只针对静态导入语句生效,不涉及 require() 动态加载等场景。

启用该规则:两种 ESLint 配置方式

本规则随默认配置自动开启。从源码可以看出:

  • 传统 .eslintrcrecommended 配置(src/configs/recommended.ts)中,storybook/no-renderer-packages 被设为 error,作用于 **/*.stories.@(ts|tsx|js|jsx|mjs|cjs)**/*.story.@(ts|tsx|js|jsx|mjs|cjs) 两类文件;
  • flat config 的 flat/recommendedsrc/configs/flat/recommended.ts)以同样方式开启,规则元信息也通过 categories: [CategoryId.RECOMMENDED] 声明其归属(见 constants.ts)。

因此,你不需要单独配置即可获得该规则,只需在项目中启用插件配置:

// .eslintrc
{
  "extends": ["plugin:storybook/recommended"]
}

或使用 flat config:

import storybook from 'eslint-plugin-storybook';

export default [
  ...storybook.configs['flat/recommended'],
];

如果你使用 .storybook 目录下的配置文件并希望插件同时检查其中的 addon 配置,需在 .eslintignore 中加入 !.storybook(flat config 中则使用 globalIgnores(['!.storybook'], ...))。更完整的安装步骤(含 ESLint 与插件版本对应关系)参见 code/lib/eslint-plugin/README.md。在仓库本体的 oxlint 示例配置 中,storybook/no-renderer-packages: "error" 同样被显式开启。

什么时候应该关闭它

如果你确实有特殊需求,需要直接在 Stories 中使用渲染器包,可以关闭该规则:

// .eslintrc overrides
{
  "overrides": [
    {
      "files": ["**/*.stories.@(ts|tsx|js|jsx|mjs|cjs)"],
      "rules": {
        "storybook/no-renderer-packages": "off"
      }
    }
  ]
}

不过,规则文档与实现都建议保留默认开启:框架包针对你的构建工具做了优化,能提供与开发环境更好的集成。需要警惕的是,仓库内各框架的渲染器实现往往同时暴露多种写法,若脱离对应框架包直接引用渲染器,容易在 Vite/Webpack/Next.js 等不同环境下产生不一致的模块解析行为。

小结

no-renderer-packages 通过一张硬编码的"渲染器 → 框架包"映射表,在编译前用 ESLint 层面拦截掉 Stories 中对渲染器基础包的直连导入,并给出可一键照抄的候选替换清单。理解这张映射表(完整版见源码 rendererToFrameworks)与它的启用范围(recommended / flat/recommended、仅针对 stories 文件),就能让你的组件测试与文档代码始终保持与所选框架包一致的集成方式。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388