首页
/ Storybook × Angular:用 Angular Builder(`ng run`)一键构建生产级静态站点

Storybook × Angular:用 Angular Builder(`ng run`)一键构建生产级静态站点

2026-09-06 19:22:55作者:蔡丛锟

导读

在 Angular 工程中把 Storybook 发布为可供任意 Web 服务器托管的静态站点,最推荐的方式并不是直接执行 storybook build,而是通过 Angular 原生的 Architect Builder——即 @storybook/angular:build-storybook,以 ng run <project>:build-storybook 一行命令驱动构建。本文结合官方文档 docs/sharing/publish-storybook.mdx 中 Angular 专属的构建片段与仓库源码,完整讲解该 Builder 的注册、配置、调用与迁移流程,帮助你掌握在 Angular Workspace 内构建、发布 Storybook 静态产物的标准做法。

为什么 Angular 项目应使用自定义 Builder 构建 Storybook

Storybook 官方发布指南将"构建静态 Web 应用"作为发布第一步,且对绝大多数框架已经内置预配置了构建命令。但对于 Angular 用户,官方文档专门做了差异化建议(发布指南 中的 <If renderer="angular"> 分支):

If you're using Angular, it's often better to use the Angular builder to build Storybook.

原因在于 @storybook/angular 框架本身就是基于 Angular 的 Architect Builder 体系实现的。在 docs/get-started/frameworks/angular.mdx 中明确说明:

The Storybook Angular builder is a way to run Storybook in an Angular workspace. It is a drop-in replacement for running storybook dev and storybook build directly.

也就是说,Angular 场景下,启动开发服务器(start-storybook)与生产构建(build-storybook)都可以纳入 angular.jsonarchitect 配置体系,与 Angular 应用自身的 build/test/lint 目标保持一致的 CLI 体验,同时还能继承 Angular 工程的 browserTarget(样式、资源等全局配置)以及内置的 Compodoc 文档生成能力。

第一步:在 angular.json 中注册 Storybook Builder 目标

使用 ng run 之前,必须先在项目 angular.jsonarchitect 段注册 storybookbuild-storybook 两个目标。完整注册示例(手动安装文档):

{
  "projects": {
    "your-project": {
      "architect": {
        "storybook": {
          "builder": "@storybook/angular:start-storybook",
          "options": {
            // The path to the storybook config directory
            "configDir": ".storybook",
            // The build target of your project
            "browserTarget": "your-project:build",
            // The port you want to start Storybook on
            "port": 6006
          }
        },
        "build-storybook": {
          "builder": "@storybook/angular:build-storybook",
          "options": {
            "configDir": ".storybook",
            "browserTarget": "your-project:build",
            "outputDir": "dist/storybook/your-project"
          }
        }
      }
    }
  }
}

其中 browserTarget 的取值格式为 project-name:builder:config,一般指向 @angular-devkit/build-angular:browser 构建目标,便于 Storybook 复用 Angular 工程中声明的 stylesassets 等选项。

Builder 名称与仓库中的注册关系

@storybook/angular:build-storybook 并非凭空存在。在框架包中通过 package.json"builders": "builders.json" 字段向外暴露两份 Builder 元数据,见 code/frameworks/angular/builders.json

{
  "builders": {
    "build-storybook": {
      "implementation": "./dist/builders/build-storybook/index.js",
      "schema": "./build-schema.json",
      "description": "Build storybook"
    },
    "start-storybook": {
      "implementation": "./dist/builders/start-storybook/index.js",
      "schema": "./start-schema.json",
      "description": "Start storybook"
    }
  }
}

构建入口配置位于 code/frameworks/angular/build-config.ts,其中将 ./src/builders/build-storybook/index.ts./src/builders/start-storybook/index.ts 分别编译为独立 Node 入口,对应 @storybook/angular/builders/build-storybook@storybook/angular/builders/start-storybook 子路径导出。

第二步:执行生产构建

注册完成后,在 Angular 工程根目录执行(这就是关联文档片段中的核心命令):

# Builds Storybook with Angular's custom builder
ng run my-project:build-storybook

命令中的 my-project 需要替换为 angular.json 中实际的项目名,build-storybook 则是上面注册的 architect 目标名。构建完成即产出 Storybook 的静态 Web 应用,可交给任何 Web 服务器托管。

构建产物的默认输出目录定义在 code/frameworks/angular/build-schema.json 中:

"outputDir": {
  "type": "string",
  "description": "Directory where to store built files.",
  "default": "storybook-static"
}

即不指定时输出到项目根目录的 storybook-static 文件夹(可在 builder 的 options 中通过 outputDir 覆盖,如文档示例中的 dist/storybook/your-project)。

对比:普通 CLI 与 Angular Builder

作为对照,非 Angular 框架或直接使用 CLI 时的构建命令是 storybook build(对应 docs/_snippets/build-storybook-production-mode.md 中展示的 npm run build-storybook / pnpm run build-storybook / yarn build-storybook)。而 Angular 专属的"with-builder"写法(docs/_snippets/angular-builder-production.md)则将构建完全交由 Angular CLI 的 Architect 运行时驱动,两者的产物都可用于后续发布。

第三步:收编为 npm scripts

为了沿用 npm run build-storybook 的团队习惯,把 ng run 命令写入 package.json 脚本即可(这正是关联文档第二个代码片段的内容):

{
  "scripts": {
    "build-storybook": "ng run my-project:build-storybook"
  }
}

ng 是 Angular CLI 的可执行文件,需要在项目开发依赖中包含 @angular/cli(框架包的 peerDependencies 要求 >=18.0.0 < 23.0.0)。

从旧式脚本迁移到 Angular Builder

如果你的项目之前是直接调用 start-storybook / build-storybook(或 storybook dev / storybook build),官方提供了两条迁移路径(迁移指南):

自动迁移

npx storybook@latest automigrate

Storybook 会自动检测配置并完成修复。

手动迁移

先按上文在 angular.json 中补上 storybookbuild-storybook 两个 architect 目标,然后修改 package.json

{
  "scripts": {
-    "storybook": "start-storybook -p 6006", // or `storybook dev -p 6006`
-    "build-storybook": "build-storybook" // or `storybook build`
+    "storybook": "ng run <project-name>:storybook",
+    "build-storybook": "ng run <project-name>:build-storybook",
  }
}

对于多项目 Workspace,每个项目都需要独立的 .storybook 目录(位于各自项目根目录),并分别执行上述注册与迁移;也可以为每个项目依次运行 npx storybook@latest init 自动生成配置,最后用 Storybook Composition 组合多个 Storybook。

迁移时的 Compodoc 说明

compodoc 已内置进 @storybook/angular,无需再单独调用。若旧脚本中显式运行了 compodoc,可一并移除:

{
  "scripts": {
-    "docs:json": "compodoc -p tsconfig.json -e json -d ./documentation",
-    "storybook": "npm run docs:json && start-storybook -p 6006",
-    "build-storybook": "npm run docs:json && build-storybook"
+    "storybook": "ng run <project-name>:storybook",
+    "build-storybook": "ng run <project-name>:build-storybook",
  }
}

在 build schema 中,compodoc 选项默认值为 truecompodocArgs 默认值为 ["-e", "json"],且 -p(tsconfig 路径)与 -d(workspace 根目录)参数总会自动附加。

Builder 完整配置选项速查

build-storybook Builder 的完整选项定义于 code/frameworks/angular/build-schema.json(该 schema 同时用于 CLI 校验)。核心选项如下:

选项 默认值 说明
browserTarget null Angular 构建目标,格式 project-name:builder:config,一般指向 @angular-devkit/build-angular:browser,用于复用 stylesassets
outputDir storybook-static 构建产物输出目录
configDir .storybook Storybook 配置目录
tsConfig TypeScript 配置文件路径(相对当前 workspace)
preserveSymlinks false 模块解析是否保留符号链接路径
loglevel info 构建日志级别:trace/debug/info/warn/error/silent
logfile 指定后将日志写入该文件
debugWebpack false 调试 Webpack 配置
enableProdMode true 关闭 Angular 开发模式及框架内断言检查
quiet false 抑制冗余构建输出
docs false 以文档模式构建 Storybook
test false 构建面向测试优化(去重文档化产物)的静态版本,适用于 CI/大型项目提速
compodoc true 构建前执行 Compodoc 生成文档
compodocArgs ["-e", "json"] 追加的 Compodoc 参数
webpackStatsJson / statsJson false 将 Webpack/构建 stats JSON 写入磁盘
previewUrl 禁用默认 Storybook preview,改用自定义 preview
styles / stylePreprocessorOptions 注入全局样式 / 预处理选项
assets [] 静态资源列表
sourceMap false source map 配置(布尔或对象)
experimentalZoneless 实验性 zoneless 变更检测

其中 test: true 对应官方文档中为大型项目/CI 场景提供的性能优化方向:默认生产构建会把全部 stories 与文档打包进产物,测试场景下可通过该选项产出更精简的版本。

源码视角:Builder 底层如何驱动 Storybook 构建

从仓库源码可以清晰看到 Angular Builder 与 Storybook 核心构建服务的关系:

  • 依赖上,@storybook/angular 同时以 peerDependency 形式依赖 @angular-devkit/architect / @angular-devkit/build-angular(Angular 18~22 范围)与 storybook,从 code/frameworks/angular/package.json 可见。
  • Builder 实现位于 src/builders/ 目录,其中 start-storybook 实现(code/frameworks/angular/src/builders/start-storybook/index.ts)通过 createBuilder 包装出符合 Architect 规范的 Builder,在内部解析 browserTarget/tsConfig 等选项后,调用 storybook/internal/core-server 提供的 buildDevStandalone 等核心服务,并通过 rxjs Observable 保持开发服务器持续运行。生产构建 build-storybook(对应 src/builders/build-storybook/index.ts,其行为有 index.spec.ts 测试覆盖)则是"drop-in replacement"的另一半——正如官方文档所述,它在内部替代了对 storybook build 的直接调用。
  • 从依赖结构看,该 Builder 依赖 @storybook/builder-webpack5(webpack 5),因此 Angular 框架当前走的是 Webpack 构建链路。

这意味着:只要沿用 Angular 官方文档的注册方式,ng run 命令会经由 @angular-devkit/architect 解析出 @storybook/angular:build-storybook,再由框架内部的 Builder 转交给 Storybook 核心构建服务完成静态站点生成。

构建产物预览与发布

静态站点构建完成后,可以本地预览验证。官方发布指南提供了通用预览命令(docs/_snippets/preview-storybook-production-mode.md):

# npm
npx http-server ./path/to/build

# pnpm
pnpm dlx http-server ./path/to/build

./path/to/build 替换为实际产物目录(未配置 outputDir 时即 storybook-static)。确认无误后,即可把产物托管到任意静态 Web 服务器(Netlify、S3、GitHub Pages 等)进行发布与团队协作评审。需要注意的是,若想进一步了解 Angular 环境下的架构细节与全部 FAQ,可继续阅读 docs/get-started/frameworks/angular.mdxdocs/sharing/publish-storybook.mdx

小结

在 Angular Workspace 中发布 Storybook 的标准姿势是:先在 angular.json 注册 @storybook/angular:build-storybook 目标,再用 ng run <project>:build-storybook 完成静态构建,最后通过 package.json 脚本固化命令。这套流程把 Storybook 完全纳入 Angular Architect 生态,既统一了 CLI 习惯,也通过 browserTarget 无缝继承应用级样式与资源配置,配合内置 Compodoc,是最贴合 Angular 工程的官方推荐方案。

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