使用Angular来使用Storybook
首先
我打算在Angular中实践Atomic Design,所以尝试使用Storybook。
由于遇到了一些问题,所以我想记录下来。
在引入过程中,官方文档和这篇文章对我很有参考价值。
https://qiita.com/Quramy/items/463ed80f0d6fcd9e3939
环境
這是我們所測試的環境。
-
- Angular: 6.0.3
- storybook: 3.4.8
引入
执行以下命令即可。
在项目中应该生成了用于storybook的文件。
npm i -g @storybook/cli
cd {対象プロジェクトのディレクトリ}
getstorybook
在 getstorybook 上进行的活动如下所述。
https://storybook.js.org/basics/guide-angular/#docs-content
请注意,如果没有将storybook相关的文件添加到src/tsconfig.app.json的exclude中,将会在angular构建时出现错误。
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/app",
"module": "es2015",
"types": []
},
"exclude": [
"src/test.ts",
"**/*.spec.ts",
"stories", // 追加
"**/**.stories.ts" // 追加
]
}
打开故事书应用。
可以通过以下命令之一启动 Storybook。在浏览器中访问 localhost:6006 可以进行确认。
yarn storybook
# or
npm run storybook
如果发生无法读取未定义的属性’compilation’的情况
听说要使用Angular6,似乎必须使用StoryBook 4.0-alpha。
如果出现了“Module build failed: Error: Cannot find module ‘babel-core’”这个错误。
安装babel-core能解决这个问题。
yarn add babel-core --dev
解决组件的依赖关系 de
举个例子,如果在故事板中使用了名为”item”的组件,同时使用了名为”price”的组件,就必须解决它们之间的依赖关系。
由于storybook不查看angular的模块文件,所以如果仅在故事板中添加了”item”组件而没有添加”price”元素,它会生气地告诉你,它不知道”price”是什么。
解决依赖关系的方法如下所示。它与模块文件类似,所以我想应该能轻松写出来。
const itemStories = storiesOf('{story名}', module);
itemStories.addDecorator(
moduleMetadata({
declarations: [
PriceComponent
],
imports: [],
providers: []
})
);
读取为全局样式的方法
我认为有时候你可能会想要引用各个组件中全局定义的样式。
在Angular中,只需要将样式添加到angular.json中即可,但是在Storybook中,与angular.json无关,因此你需要自己实现全局的引用。
在scss的情况下,您可以在story文件(src/stories/*.stories.ts)中通过以下方式导入目标文件。
import '!style-loader!css-loader!sass-loader!../styles.scss';
在 CSS 的情况下,只需要 sass-loader 而不需要 scss。
import '!style-loader!css-loader!../styles.css';
使用旋钮
knobs是一个可以在storybook上动态更改component的输入值的插件。由于默认情况下没有包含在内,所以需要手动添加。
yarn add @storybook/addon-knobs --dev
将其添加到storybook/addons.js中。
import '@storybook/addon-actions/register';
import '@storybook/addon-links/register';
import '@storybook/addon-notes/register';
import '@storybook/addon-knobs/register'; // 追加
这个故事中会给组件添加knobs。如果是用Angular,则需要导入适用于Angular的knobs。
import { withKnobs, text, number, color, object } from '@storybook/addon-knobs/angular';
const itemStories = storiesOf('{story名}', module);
txtContainerStories.addDecorator(withKnobs);
在导入时,以src为起点使用路径进行导入。
在使用angular时,如果要在scss或ts文件中导入其他文件,可以从任何文件中使用以下方式以src为起点编写路径(取决于tsconfig的配置)。
// e.g.
import { ButtonComponent } from 'src/app/shared/button/button.component.ts';
// e.g.
@import 'src/variables/colors.scss';
然而,在storybook中,它无法解决路径,导致出现错误。
这也需要自己解决。
方法是通过扩展storybook的webpack配置来实现。
-
- 在storybook的根目录下创建webpack.config.js文件。
webpack.config.js
const genDefaultConfig = require(‘@storybook/angular/dist/server/config/defaults/webpack.config.js’);
const path = require(‘path’);
module.exports = (baseConfig, env) => {
const config = genDefaultConfig(baseConfig, env);
return config;
};
添加设置以解决src路径的别名。这样,在导入时即使从src指定,storybook也不会抱怨。
webpack.config.js
const genDefaultConfig = require(‘@storybook/angular/dist/server/config/defaults/webpack.config.js’);
const path = require(‘path’);
module.exports = (baseConfig, env) => {
const config = genDefaultConfig(baseConfig, env);
// 追加
config.resolve = {
…config.resolve,
alias: {
src: path.resolve(__dirname, ‘../src’)
}
};
return config;
};
我觉得未来还会有其他情况需要自己扩展webpack的配置,所以最好一开始就准备好webpack.config.js。
静态文件的引用
我认为经常会有在组件等中引用assets下的图像或图标的情况,但要在storybook中加载assets文件,需要在启动或构建时添加选项。
打开package.json并修改scripts。
{
"name": "test-project",
"version": "0.0.0",
"scripts": {
// 省略...
"storybook": "start-storybook -p 6006 -s ./src", // 修正
"build-storybook": "build-storybook -s ./src" // 修正
},
// 省略...
}
我正在做的是添加一个名为static-dir的选项。这样,在构建时,生成的目录中将包含一个名为assets的目录,从storybook上也可以引用该目录。为什么指定的值不是assets而是src呢?因为只有指定目录中的文件和子目录会被展开,而指定的目录本身不会被展开。在angular中引用图像等时,通常会使用assets/image/item.png这样的路径,但如果在static-dir选项中指定了assets,那么只能通过image/item.png引用。但是,如果指定src,将会生成很多不必要的文件,如果您知道更好的方法,请务必告诉我!
最后
虽然遇到了一些问题,但是能够将组件列出并关联起来,非常方便!而且根据atomic design的理念构建,使得组件的可重用性增强,代码维护也更容易,简直是一大福利。虽然一开始可能会花费一些时间,但是我希望从现在开始都能意识到atomic design并进行开发。