NX - 带有 Storybook 和单独导出组件的 UI 库
Posted
技术标签:
【中文标题】NX - 带有 Storybook 和单独导出组件的 UI 库【英文标题】:NX - UI Library with Storybook and individually exported components 【发布时间】:2020-07-11 08:57:22 【问题描述】:我正在探索 Nx 与 Angular(对两者都相对较新)并试图弄清楚如何生成一个组件库:
可以运行 Storybook,并且 可以一次导入一个组件,而不是将整个模块/所有组件拖到需要单个组件的应用程序中。 (为了避免在我的包中添加不必要的代码/膨胀)。所以理想的设置是这样的:
repo
|--apps
|--normal-app (can import just card or button, without pulling in both)
|--libs
|--ui (lists individually exportable components, and has a servable Storybook)
|--.storybook
|--card
|--button
按照展示如何创建共享组件库的通用 Nx 教程以及设置 Storybook in Nx 的指南,我生成了一个 UI 库,并设置了一个 Storybook 示意图(如果这是正确的方法说出来)为那个lib目录。
希望将我所有的共享组件放在一个库中,并将 Storybook 设置为自动生成并为每个组件提供故事——但随后能够单独从该库中将组件拉入其他应用程序 /em> 引入整个庞大的 UI 库。
我成功构建了一个 UI 库和其中的两个组件。我在该库中成功设置了 Storybook。然后,我从 UI 库中的 index.ts
文件(公共 API)导入了 UIModule
,并在我的模板中使用了这两个组件之一。
但是当我构建导入 lib 的应用程序时,生产构建包含 两个 组件,尽管我使用了一个。这是有道理的,因为我正在导入UiModule
。然而,这并不理想。
我希望创建一个设置,允许在带有 Storybook 设置的库中并置组件,可以单独导入。
有没有办法在不大幅改变 NX 设置的情况下做到这一点?到目前为止,我已经探索了两个主要选项。一种是将所有组件分解为它们自己的 UI 库,将它们全部导入为 Storybook 设置的单独应用程序中,然后将它们单独导入到主应用程序中。像这样(尝试#1):
repo
|--apps
|--storybook-app (imports all)
|--other-app (imports just button)
|--libs
|--button
|--card
不过,这并不理想,原因如下:
它不对组件进行分组。 它涉及更多的 lib 样板。 它不会为每个组件自动生成故事。 它要求开发者记住为每个组件添加一个故事到故事书中。作为第二次尝试 (#2),我尝试将每个组件生成为共享目录中的单独库:
repo
|--apps
|--storybook-app (imports all)
|--other-app (imports just button)
|--libs
|--ui (just a directory; not a "project")
|--button (module; has separate component dir beneath)
|--card
这有很多缺点:
仍然无法自动生成故事。 不清楚我的故事书应该放在哪里。它是一个独立的应用程序,如上面的树形图吗?这似乎不习惯。我试图将它放在ui
目录中,但由于这不是一个“项目”,所以当我尝试使用 VSCode NX 扩展名时,我会得到一个Cannot find project 'ui'
。
我必须为每个 UI 组件在一个库中生成一个库和一个组件。这是额外的样板文件和额外的代码以及额外的出错机会。
在我看来,Storybook 不应该是一个应用程序,因为它可以正常服务,但有自己的服务命令。
我可以构建上述版本之一(可能是#2),但我怀疑对于看似常见的用例有最佳实践。看来我的大部分困惑源于 Angular 依赖注入。 (在 React 应用程序中,您可以只导入一个组件,但在 Angular 中,每个组件都属于一个模块,并且特别需要注入。拥有特定于组件的模块是一种不好的做法吗?)
有谁知道满足这些理想规范的惯用/最佳实践方式(与单独导出的组件共享故事书库,或在 NX 中使用自动生成的故事拆分组件)?
【问题讨论】:
使用了一年多后,您对接受的答案感觉如何? 最终走向完全不同的方向,因为客户规格发生了变化,所以不能说真的很遗憾。 【参考方案1】:我还没有为这个问题找到完全令人满意的解决方案,但这就是我最终要做的。它接近上面的#2:
-
创建了一个
libs/ui
目录(不是项目)
构建生成器脚本,将每个组件创建为该目录中自己的单独模块,并在其中自动创建故事脚手架。
创建了一个component-lib
库。 (而不是应用程序,因为 Storybook 有自己独立的运行命令)。
使用 Nx CLI 在其中设置 Storybook 配置。
更改了 Storybook 配置以获取 所有 .stories.ts
文件在 libs/ui
目录下。
这样,component-lib
目录会自动添加每个添加的新组件,我不必担心每次添加组件时都会出现一堆样板文件。此外,每个组件都可以单独导入,无需拖入包中。
我不会分享我的整个组件生成器脚本,但它是一个基本的 JS 文件,
-
运行 Nx 库生成器以在
ui
目录中生成库
运行 Nx 组件生成器以在该库中生成组件。
使用fs
在该库中写入适当的.stories.ts
文件。
然后,在我的component-lib
目录中,我将.storybook/config.js
中的最后一行修改为要求ui
库下的所有 个故事:
configure(require.context('../../ui', true, /\.stories\.tsx?$/), module);
这一切都让人感觉有点 hacky,尤其是生成器脚本。但它有效!
【讨论】:
你是如何管理依赖图的? component-lib 中一个组件的更改不会将所有应用标记为受影响,无论该应用是否正在使用该组件?【参考方案2】:您还可以使用您的初始方法并为您想要提供的每个组件集(甚至只有一个组件)生成一个模块(不是库)。然后导出 index.ts 中的所有模块
nrwl/nx 中的 Angular 库必须包含至少一个模块(数据库除外),就像您的普通 Angular 项目必须包含 app.module 一样。但这并不意味着您不能在整个 lib 中拥有多个模块 exportet。使用多个模块,您可以从您的库中独立导入它们。
例子
import module1 from '@mylib'
import module2 from '@mylib'
【讨论】:
以上是关于NX - 带有 Storybook 和单独导出组件的 UI 库的主要内容,如果未能解决你的问题,请参考以下文章
如何导出在 storybook 中创建的 React Native 组件以便在实际应用中使用?