Storybook v3.3.0でAngular対応がリリースされたので、さっそく試してみました1。
Angular CLIプロジェクトへの導入方法
Angular CLIで作成したプロジェクトに導入するのであれば、コマンド一発です。
ng new my-ng-storybook-prj
cd my-ng-storybook-prj
yarn add @storybook/cli --dev
yarn run getstorybook
これで完了です。
package.jsonに storybook
と build-storybook
scriptが定義されているので、こいつを叩くだけです。
yarn run storybook
localhost:6006
でstorybookが起動します。
ちゃんとHMRにも対応しています。
もちろんReactやVue版と同じく、yarn run build-storybook
を実行することで、storybookを静的なサイトとして出力することも可能です。
現状、 getstorybook
で作成される設定では、storyを .js
で記述するようになっていますが、TypeScriptに変えたい!という場合はWebpackのRequire Contextを修正しておくとよいです。
どう考えても.tsの方が良いに決まっているので、PR出して修正済み。
// automatically import all files ending in *.stories.js
const req = require.context('../stories', true, /.stories.ts$/); //ここね
function loadStories() {
req.keys().forEach((filename) => req(filename));
}
configure(loadStories, module);
Angular版Storyの記述方法
Storyを書く際は、@storybook/angular
の storiesOf
を使います。
storiesOf('Awesome Button', module).add('to Storybook', () => ({
component: AwesomeButtonComponent,
props: {
name: 'Button',
myClick: action('Clicked!'),
},
}));
対象のComponentと、propsを指定するのが基本です。
propsは、対象が @Input
であれば入力として、 @Output
であればEventEmitterが発火したタイミングで呼び出されるコールバック関数を指定します。
単純なComponentであればこれでよいのですが、そのComponentを動作させるためのモジュール設定が必要な場合は、さらに moduleMetadata
を指定できます。
storiesOf('Awesome Button', module).add('to Storybook', () => ({
component: AwesomeButtonComponent,
props: { /*...*/ },
moduleMetadata: {
imports: [],
schemas: [],
declarations: [],
providers: []
}
}))
Angularの単体テストを書いたことがある人であれば、下記のようなテスト用モジュール設定には馴染みがあると思います。Storybookの moduleMetadata
も役割は同じです。
TestBed.configureTestingModule({
declarations: [ BannerComponent ],
providers: [
{ provide: ComponentFixtureAutoDetect, useValue: true }
]
})
Storyの書き方の詳細については、 https://github.com/storybooks/storybook/tree/master/examples/angular-cli/src/stories に色々とサンプルがあるので、こちらも参考にするとよいでしょう。
css関係の諸注意
現状のStorybookはAngular CLIには特に依存しない作りになっています。このため、Componentのstyle周りについては、多少のworkaroundを施す必要があります2。
const genDefaultConfig = require('@storybook/angular/dist/server/config/defaults/webpack.config.js');
module.exports = (baseConfig, env) => {
const config = genDefaultConfig(baseConfig, env);
// Overwrite .css rule
const cssRule = config.module.rules.find(rule => rule.test && rule.test.toString() === '/\\.css$/');
if (cssRule) {
cssRule.exclude = /\.component\.css$/;
}
// Add .scss rule
config.module.rules.unshift({
test: /\.scss$/,
loaders: ['raw-loader', 'sass-loader'],
});
return config;
};
本当はAngular CLIのmodelを参照して、同じruleを適用するようにすべきなのでしょうが、ちょっと複雑になりそうなので今後の宿題にします。
おわりに
さくっとStorybook + Angularの使い方を見てきましたが如何でしょうか。導入するのは本当に簡単なので、ぜひAngularでComponentガイドを作ってみてほしいです。
あと、tsuyoshiwada/storybook-chrome-screenshot のAngular版があれば、CIでStorybookについてキャプチャをとって、reg-suit で画像スナップショットテストを回す、みたいなこともできそうなので、色々と夢が広がりますね。
折角なので、自分でPR作ったので、mergeしてもらいました。これで Angular + Storybook + Screenshot + Snapshot test という構成のプロジェクトがAngular CLIベース作れるようになったので、 Quramy/angular-sss-demo にデモレポジトリを作っています。
それでは、また。
-
Angularアドカレのネタにしようかな、とも思ってたのですが、若干タイミングがズレてたのでCDK優先にしました ↩
-
https://storybook.js.org/basics/guide-angular/#configure-style-rules ↩