Slide 1

Slide 1 text

1 © 2012-2021 BASE, Inc. TypeScript Compiler API で Storybook を置換した話と その次の話 TECH STAND #6 TypeScript プログラミングをするパンダ (@Panda_Program)

Slide 2

Slide 2 text

2 © 2012-2021 BASE, Inc. 自己紹介

Slide 3

Slide 3 text

3 © 2012-2021 BASE, Inc. 自己紹介 プログラミングをするパンダ(@Panda_Program) 所属  BASE株式会社(2021年5月入社)  Product Dev Division / Owners Experience Frontend Team 業務内容  新規機能開発、DX向上のための改善、  社内用UIコンポーネント集のメンテナンスなど。 #tech_stand @Panda_Program

Slide 4

Slide 4 text

4 © 2012-2021 BASE, Inc. 自己紹介 プログラミングをするパンダ(@Panda_Program) 趣味  Next.js を使った Web サイトの個人開発  最近は note の記事を PDF 化 するツールを作った。  note PDFy  https://note-pdfy.panda-program.com/ #tech_stand @Panda_Program

Slide 5

Slide 5 text

5 © 2012-2021 BASE, Inc. BASE, Inc.の紹介

Slide 6

Slide 6 text

6 © 2012-2021 BASE, Inc. ネットショップ作成サービス「BASE」 #tech_stand @Panda_Program

Slide 7

Slide 7 text

7 © 2012-2021 BASE, Inc. 今日お話しすること

Slide 8

Slide 8 text

8 © 2012-2021 BASE, Inc. TypeScript Compiler API で Storybook の コンポーネントを置換した話

Slide 9

Slide 9 text

9 © 2012-2021 BASE, Inc. 今日お話しすること TypeScript Compiler API で Storybook の コンポーネントを置換した話(7分) 1 JS のメタプログラミング用のツールとそのユースケース - jscodeshift を中心に(7分) まとめと反省とその次の話(1分) 2 3 #tech_stand @Panda_Program

Slide 10

Slide 10 text

10 © 2012-2021 BASE, Inc. 今日お話しすること TypeScript Compiler API で Storybook の コンポーネントを置換した話 1 ● 作成したスクリプトをコンポーネントに適用 ● import 文の書き換えを紹介します ● メタプロのコードと処理の流れ #tech_stand @Panda_Program

Slide 11

Slide 11 text

11 © 2012-2021 BASE, Inc. 前提 ● 半年前、Storybook は v5 で storiesOf で書かれていた ● CSF(Component Story Format)に書き換えて v6 にしたい ● コンポーネント数のファイル数は40ほどだった。人海戦術は使いたくない ● TypeScript Compiler API(以下、Compiler API)でメタプログラミングをした #tech_stand @Panda_Program

Slide 12

Slide 12 text

12 © 2012-2021 BASE, Inc. コストは「人海戦術 > ツール作成」 https://devblog.thebase.in/entry/typescript-compiler-api-storybook #tech_stand @Panda_Program

Slide 13

Slide 13 text

13 © 2012-2021 BASE, Inc. Compiler API とは何か 「TypeScript Compiler API とは、TypeScript の Compiler を操作するための API です。 つまり、TS/JS のコードを解析したり、TS を JS に変換したり、コー ドの文法エラーを検出するといったコンパイラの機能を利用するための API で す」 https://devblog.thebase.in/entry/typescript-compiler-api-storybook Compiler API の機能の一部を使って、 コードを書き換えることができる (=メタプログラミングができる) #tech_stand @Panda_Program

Slide 14

Slide 14 text

14 © 2012-2021 BASE, Inc. 作成したスクリプトを コンポーネントに適用

Slide 15

Slide 15 text

15 © 2012-2021 BASE, Inc. Before #tech_stand @Panda_Program

Slide 16

Slide 16 text

16 © 2012-2021 BASE, Inc. After #tech_stand @Panda_Program

Slide 17

Slide 17 text

17 © 2012-2021 BASE, Inc. import 文の書き換えを 紹介します

Slide 18

Slide 18 text

18 © 2012-2021 BASE, Inc. import 文の書き換えを紹介します 今回は時間の都合上 import 文の書き換え部分だけ紹介します。 その他の箇所の説明はブログ記事を読んでいただくか、 または GitHub レポジトリをご覧ください。 ブログ https://devblog.thebase.in/entry/typescript-compiler-api-storybook レポジトリ https://github.com/baseinc/panda-storybook-v5-to-v6 #tech_stand @Panda_Program

Slide 19

Slide 19 text

19 © 2012-2021 BASE, Inc. import 文の書き換えを紹介します 変換前 変換後 #tech_stand @Panda_Program

Slide 20

Slide 20 text

20 © 2012-2021 BASE, Inc. import 文の書き換えを紹介します ● @storybook/vue、storybook-addon-vue-info の import 文を削除 ● knob の text の import を削除 ● README の import のパスを変更('../../values/Devices' → './README.md') 変更点 #tech_stand @Panda_Program

Slide 21

Slide 21 text

21 © 2012-2021 BASE, Inc. メタプロのコードと 処理の流れ

Slide 22

Slide 22 text

22 © 2012-2021 BASE, Inc. メタプロのコードと処理の流れ #tech_stand @Panda_Program

Slide 23

Slide 23 text

23 © 2012-2021 BASE, Inc. メタプロのコードと処理の流れ 1. ファイルを読み込む #tech_stand @Panda_Program

Slide 24

Slide 24 text

24 © 2012-2021 BASE, Inc. メタプロのコードと処理の流れ ● printRecursive で再帰的に AST を探索する ● isImportDeclaration で    import 文で条件分岐する ● 配列 imports に import 文を格納する 次に imports に格納された テキストを処理をする ex. [ “import { storiesOf } from '@storybook/vue'”] 2,3. AST を解析して、import 文を配列に追加する #tech_stand @Panda_Program

Slide 25

Slide 25 text

25 © 2012-2021 BASE, Inc. メタプロのコードと処理の流れ ● filter で不要な import を削除 ● concat で 必要な import 追加 ● join で文字列に変換 ● replace で import 文を部分的に書き 換え 泥臭い処理だが、 AST をいじるより 目的達成が簡単 4. import 文を書き換える #tech_stand @Panda_Program

Slide 26

Slide 26 text

26 © 2012-2021 BASE, Inc. メタプロのコードと処理の流れ 5. ファイルとして出力する #tech_stand @Panda_Program

Slide 27

Slide 27 text

27 © 2012-2021 BASE, Inc. メタプロのコードと処理の流れ 大まかにこのような書き換えを 色々なパターンで適用する ● 文字列置換 ● TypeScript AST Viewer を使ってコード 生成 ブログ記事にして公開した 「TypeScript Compiler API で40の Storybook コンポーネントを storiesOf から CSF(Component Story Format)に置換した」 https://devblog.thebase.in/entry/typescript-compiler-api-storybook #tech_stand @Panda_Program

Slide 28

Slide 28 text

28 © 2012-2021 BASE, Inc. JS のメタプログラミング用の ツールとそのユースケース - jscodeshift を中心に

Slide 29

Slide 29 text

29 © 2012-2021 BASE, Inc. 今日お話しすること JS のメタプログラミング用のツールとそのユースケース - jscodeshift を中心に 2 ● 記事のTwitterでの反響 ● コンポーネントに適用してみた ● Compiler API と jscodeshift のコードを比較する ● 比較まとめ ● JS のメタプロのツールについてさらに調べてみた ● メタプロのツールまとめ #tech_stand @Panda_Program

Slide 30

Slide 30 text

30 © 2012-2021 BASE, Inc. 記事のTwitterでの反響

Slide 31

Slide 31 text

31 © 2012-2021 BASE, Inc. azu さん Babel や jscodeshift や Semgrep 👀 https://twitter.com/azu_re/status/1438385998929428482 #tech_stand @Panda_Program

Slide 32

Slide 32 text

32 © 2012-2021 BASE, Inc. berlysia さん 公式 codemod 👀 https://twitter.com/berlysia/status/1438371985294127110 #tech_stand @Panda_Program

Slide 33

Slide 33 text

33 © 2012-2021 BASE, Inc. 公式 codemod ?

Slide 34

Slide 34 text

34 © 2012-2021 BASE, Inc. 😱

Slide 35

Slide 35 text

35 © 2012-2021 BASE, Inc. before #tech_stand @Panda_Program

Slide 36

Slide 36 text

36 © 2012-2021 BASE, Inc. after #tech_stand @Panda_Program

Slide 37

Slide 37 text

37 © 2012-2021 BASE, Inc. before/after https://github.com/storybookjs/storybook/blob/master/lib/codemod/src/transforms/storiesof-to-csf.js #tech_stand @Panda_Program

Slide 38

Slide 38 text

38 © 2012-2021 BASE, Inc. 適用してみた

Slide 39

Slide 39 text

39 © 2012-2021 BASE, Inc. before #tech_stand @Panda_Program

Slide 40

Slide 40 text

40 © 2012-2021 BASE, Inc. after #tech_stand @Panda_Program

Slide 41

Slide 41 text

41 © 2012-2021 BASE, Inc. コードリーディング せっかくなのでコードを覗いてみた 内部では jscodeshift が使われている。 #tech_stand @Panda_Program

Slide 42

Slide 42 text

42 © 2012-2021 BASE, Inc. コードリーディング せっかくなのでコードを覗いてみた 内部では jscodeshift が使われている。 ざっくり処理内容 ● コンポーネント名、Decorators や Parameters を抽出してメタ情報を作成 ● add の数だけ Story を作成 ● add の第二引数(コンポーネント)には手を加えない #tech_stand @Panda_Program

Slide 43

Slide 43 text

43 © 2012-2021 BASE, Inc. コードリーディング #tech_stand @Panda_Program Compiler API で実装したのと 同じ処理は jscodeshift で どのように書くのだろう🤔

Slide 44

Slide 44 text

44 © 2012-2021 BASE, Inc. Compiler API と jscodeshift の コードを比較する

Slide 45

Slide 45 text

45 © 2012-2021 BASE, Inc. 比較1: 探索 #tech_stand @Panda_Program

Slide 46

Slide 46 text

46 © 2012-2021 BASE, Inc. 比較1: 探索 #tech_stand @Panda_Program

Slide 47

Slide 47 text

47 © 2012-2021 BASE, Inc. 比較2: オブジェクトの作成 #tech_stand @Panda_Program

Slide 48

Slide 48 text

48 © 2012-2021 BASE, Inc. 比較2: オブジェクトの作成 #tech_stand @Panda_Program

Slide 49

Slide 49 text

49 © 2012-2021 BASE, Inc. 比較3: export 文の作成 #tech_stand @Panda_Program

Slide 50

Slide 50 text

50 © 2012-2021 BASE, Inc. 比較3: export 文の作成 変数 key に Story(変数名)、 変数 val に () => { return { ... } }(即時関数)が格納されているとする #tech_stand @Panda_Program

Slide 51

Slide 51 text

51 © 2012-2021 BASE, Inc. 比較まとめ

Slide 52

Slide 52 text

52 © 2012-2021 BASE, Inc. 比較まとめ azu さんの指摘の通り、jscodeshift の方がコード量が少ない。 結果、処理内容を辿りやすいためメンテナンスができる。 #tech_stand @Panda_Program

Slide 53

Slide 53 text

53 © 2012-2021 BASE, Inc. JS のメタプロの ツールについて さらに調べてみた

Slide 54

Slide 54 text

54 © 2012-2021 BASE, Inc. JS のメタプロのツールについてさらに調べてみた azu さんの Dive into AST 様々なツール(自作、ESLint、Babel、jscodeshift)で 同じ処理をするコードの比較をしている ● コードの中にある eval 関数の有無判定を正規表現やESLintで行う ● console.logの置換・削除を Babel、jscodeshiftで行う https://dive-into-ast.netlify.app/ #tech_stand @Panda_Program

Slide 55

Slide 55 text

55 © 2012-2021 BASE, Inc. JS のメタプロのツールについてさらに調べてみた https://dive-into-ast.netlify.app/47 #tech_stand @Panda_Program

Slide 56

Slide 56 text

56 © 2012-2021 BASE, Inc. JS のメタプロのツールについてさらに調べてみた Semgrep は指定したパターンにマッチしたものを 抜き出して、別のものに置き換えていくイメージ AST の操作というより、「文字列置換 + α」の 要件ならこちらのツールが適している感じがする Semgrep https://semgrep.dev/ https://efcl.info/2020/12/04/semgrep/ #tech_stand @Panda_Program

Slide 57

Slide 57 text

57 © 2012-2021 BASE, Inc. JS のメタプロのツールについてさらに調べてみた Compiler API の業務での使い所は 型の生成くらい? yml から TS の型を生成するというのをやってみたことがある 「TypeScript Compiler API で型を自動生成する」 https://zenn.dev/panda_program/articles/typescript-compiler-api 他にもこんなところで使ったよ、という話があればぜひ教えて欲しいです また、TS の graphql-codegen はどうやって型生成してるんだろう(コード追いきれなかった) #tech_stand @Panda_Program

Slide 58

Slide 58 text

58 © 2012-2021 BASE, Inc. メタプロのツールまとめ

Slide 59

Slide 59 text

59 © 2012-2021 BASE, Inc. メタプロのツールまとめ ● JS / TS でメタプロをする際は、 要件に応じて使うツールを変えると良い ● ライブラリのバージョンアップの際には 公式がマイグレーションツールを出しているかチェックする (React も codemod を出している) https://github.com/reactjs/react-codemod #tech_stand @Panda_Program

Slide 60

Slide 60 text

60 © 2012-2021 BASE, Inc. まとめと反省と その次の話

Slide 61

Slide 61 text

61 © 2012-2021 BASE, Inc. 今日お話しすること まとめと反省とその次の話 3 ● 反省点 ● Next Action(次の話) ● まとめ #tech_stand @Panda_Program

Slide 62

Slide 62 text

62 © 2012-2021 BASE, Inc. 反省点

Slide 63

Slide 63 text

63 © 2012-2021 BASE, Inc. 反省点 Compiler API のコードを書きながら、 「このコードのメンテナンスはできない」 「一度きりの書き捨てスクリプトだ」と 感じていたので、やっぱりやりすぎだったかなと 思った 解の質がイシューの質に見合っていない オーバーエンジニアリングとは、 「イシューの質に対して解の質が高すぎる」こと 『イシューからはじめよ』(安宅和人著、 EIJI PRESS社) p.25 図を元に改変 #tech_stand @Panda_Program

Slide 64

Slide 64 text

64 © 2012-2021 BASE, Inc. 反省点 実行の前に調べ尽くそう。 人の書いたコード(ツール)を使うことで 時間・労力を節約できる。 そもそも公式で codemod が用意されている 「ソフトウェアの梃子(レバレッジ)を 有効に活用する」 (『UNIXという考え方』の定理6) #tech_stand @Panda_Program

Slide 65

Slide 65 text

65 © 2012-2021 BASE, Inc. よかった点 stand.fm さんの TECH STAND の TS 回に誘っていただけたのでよかった 人間万事塞翁が馬 #tech_stand @Panda_Program

Slide 66

Slide 66 text

66 © 2012-2021 BASE, Inc. Next Action (次の話)

Slide 67

Slide 67 text

67 © 2012-2021 BASE, Inc. Next Action(次の話) Storybook v6.4 から CSF 3.0 が導入される (2021/11/8 時点では v6.4 は beta 版) 書き方がまた変わるものの、 ボイラープレートがさらに減る https://storybook.js.org/blog/component-story-format-3-0/ もうすぐ CSF 3.0 が来る #tech_stand @Panda_Program

Slide 68

Slide 68 text

68 © 2012-2021 BASE, Inc. Next Action(次の話) 例1: title が不要になる #tech_stand @Panda_Program

Slide 69

Slide 69 text

69 © 2012-2021 BASE, Inc. Next Action(次の話) 例2: ストーリーをオブジェクトとして使える #tech_stand @Panda_Program

Slide 70

Slide 70 text

70 © 2012-2021 BASE, Inc. Next Action(次の話) 例3: コンポーネントのデフォルトの定義が極限までシンプルになる #tech_stand @Panda_Program

Slide 71

Slide 71 text

71 © 2012-2021 BASE, Inc. Next Action(次の話) CSF 3.0 用の codemod が準備されている $ npx sb@next migrate csf-2-to-3 --glob="**/*.stories.js v6.4 がリリースされたら、codemod を使ってコンポーネントを書き換えよう もし細かい修正が必要な場合は、 jscodeshift で対応する #tech_stand @Panda_Program

Slide 72

Slide 72 text

72 © 2012-2021 BASE, Inc. まとめ

Slide 73

Slide 73 text

73 © 2012-2021 BASE, Inc. まとめ ● 発信をすると逆に色々教えて貰える ● JS のメタプロツールはユースケースに応じて使い分ける ● メタプログラミングは面白い #tech_stand @Panda_Program

Slide 74

Slide 74 text

74 © 2012-2021 BASE, Inc. ご静聴 ありがとうございました