Slide 1

Slide 1 text

Turborepo Code Generationによる、 サイバーエージェントグループの フロントエンド開発の効率化 UIT Meetup vol.20『これがぼくらのスタンダード』 Shuta Hirai

Slide 2

Slide 2 text

Shuta Hirai 株式会社サイバーエージェント グループIT推進本部 CyberAgent group Infrastructure Unit(CIU) フロントエンドエンジニア Social Accounts ・https://github.com/shuta13 ・https://twitter.com/did0es 週末は代々木公園でフットサルをして、 松屋で朝食を食べるのが僕のスタンダードです

Slide 3

Slide 3 text

1.CIUのフロントエンドについて 2.開発における課題 3.Code Generationによる開発の効率化 4.CIUにおける活用方法の紹介 5.所感・まとめ

Slide 4

Slide 4 text

CIUのフロントエンドに ついて

Slide 5

Slide 5 text

CIU: CyberAgent group Infrastructure Unit

Slide 6

Slide 6 text

CIU: サイバーエージェントグループの インフラ組織

Slide 7

Slide 7 text

プライベートクラウドや KaaS・IaaSなどのサービス開発、 全社インフラの支援を行っています

Slide 8

Slide 8 text

CIUのフロントエンドの主な業務:

Slide 9

Slide 9 text

CIUのフロントエンドの主な業務: サービスの管理画面の開発

Slide 10

Slide 10 text

CIUの展開するサービス数

Slide 11

Slide 11 text

20

Slide 12

Slide 12 text

CIUのフロントエンドエンジニア数

Slide 13

Slide 13 text

2

Slide 14

Slide 14 text

開発における課題

Slide 15

Slide 15 text

①人手が足りない

Slide 16

Slide 16 text

サービス数 > 人数 前述のとおり、サービス数に対して人手が足りていない ・20個あるサービス全ての管理画面を作るわけではないが、それでも足りていない 基本全てのフロントエンドを2人が見る状態 ・フロントエンドの設計・実装・運用全て2人で担当 ・さすがに全部は見きれないので、一部(20 - 30%程度)の実装は外注 ・マネジメント系のタスクも発生する

Slide 17

Slide 17 text

②コピペの多用

Slide 18

Slide 18 text

管理画面の例

Slide 19

Slide 19 text

似たような画面の開発 社内向け管理画面 ・基本、新規が出る際は毎回似た構成の画面 ・提供したいものはあくまでCUIだったもののGUI版 似ている → 使いまわせる ・ドメインは違えど、ほとんどUIは変わらない ・UI以外もほとんど変わらない ・データ取得、アーキテクチャ、ディレクトリ構成etc…

Slide 20

Slide 20 text

ファイル数とコピペの問題 使い回せるが故に、既存からコピペを繰り返す ・数枚程度のファイルであれば良いが、数10 〜 100では... ・人為的なミスが発生しうる可能性がどんどん上がる フロントエンドの構成上、ファイル数が増えがち ・Clean Architecture によってデータ取得・更新の流れをわかりやすく ・実装の見通しは良いが、その分ファイル数がかさむ ・コピペしていては腱鞘炎になりかねない

Slide 21

Slide 21 text

③外部のコードの混在

Slide 22

Slide 22 text

外注の話 ・はじめに要件を提示して、成果物を貰う方式 ・密に連携が取れるわけではない ・どうしてもレビューにラグが生じる ・開発規約の変更があれば逐一共有する ・なるべく揃えて、こちらで巻き取って修正はしないようにしたい ・より機械的に、手数少なく共有できると◎

Slide 23

Slide 23 text

解決の方針:

Slide 24

Slide 24 text

解決の方針: 開発の工数が少なく事故りにくく、 外注もしやすい環境を実現する

Slide 25

Slide 25 text

ノーコードツールを使えば 良いのでは?

Slide 26

Slide 26 text

🙅 (not for us)

Slide 27

Slide 27 text

我々はエンジニア 技術的挑戦の機会を捨てたくはない ・エンジニアがいない組織ではない ・自分たちの成長の機会も必要 仮にノーコードツールを選定したとして ・メンテは必要 ・サービスによって生成物を柔軟に変えられない(ことが多い) ・結局コードをいじることになる

Slide 28

Slide 28 text

プロジェクトのtemplateを作れば 良いのでは?

Slide 29

Slide 29 text

🙆 (good)

Slide 30

Slide 30 text

プロジェクトのtemplateを作る場合 コピペしなくてよくなる ・CUI・GUIで画面を生成できる ・生成したコードを変更してリリース コード自体がExampleの役割を担える ・生成したコードを見れば、実装の方針がある程度わかる template自体のメンテは必要 ・依存パッケージの更新、バグ修正など ・雛形から作ったサービスの更新も必要

Slide 31

Slide 31 text

ファイルのtemplateを作れば 良いのでは?

Slide 32

Slide 32 text

🙆🙆 (great)

Slide 33

Slide 33 text

No content

Slide 34

Slide 34 text

Code Generationによる 開発の効率化

Slide 35

Slide 35 text

ファイルのtemplateを作る場合 コピペしなくてよくなる・規約で縛れる ・プロジェクトのtemplateと同様 依存パッケージの更新など、重いメンテは必要なくなる ・templateの更新だけで済む ・影響範囲を絞れる ・ダブルメンテ感は減る ・書き方が変わった箇所は、grepして修正 ・(頑張れば)自動化もできる

Slide 36

Slide 36 text

(再掲) 解決の方針: 開発の工数が少なく事故りにくく、 外注もしやすい環境を実現する

Slide 37

Slide 37 text

解決方法の整理 開発の工数が少ない状態 → 必要なファイルを既存から人力で探すのではなく、CLIでtemplateから生成 事故りにくい状態 → コピペしない templateは常に正しいものにする 外注しやすい状態 → CLIの使い方だけ説明すれば、規約通りに実装が進められるようにする

Slide 38

Slide 38 text

解決手段 : Code Generation コードの自動生成 ・CLIの引数とtemplateから、コードを吐き出す 自動生成向けツールの例 ・Plop: https://plopjs.com ・Yoeman: https://yeoman.io ・Hygen: https://www.hygen.io

Slide 39

Slide 39 text

ところで、

Slide 40

Slide 40 text

ところで、 CIUではTurborepoを利用しています

Slide 41

Slide 41 text

なぜTurborepoなのか Lernaからの移行 ・LernaをTurborepo + lerna-liteに置き換えたのがきっかけ ・Lernaほど大きなものは我々には不要だった ・publishはYarnやlerna-liteで賄える Turborepoを選んだ背景 ・モノレポ管理 + α ・ビルドシステムの整備 ・@turbo/gen

Slide 42

Slide 42 text

なぜTurborepoなのか @turbo/gen ・packageやprojectをCLIから作成できる、コード自動生成ツール ・基本は、既存のpackageのコピペをCLIで行う形 ・templateからの生成も可能 ・JSとHandlebarsで書く ・拡張性◎で直感的 ・InquirerやPlopのAPIを使える

Slide 43

Slide 43 text

Turborepoって昔からコード生成 できたっけ...?

Slide 44

Slide 44 text

Turborepoって昔からコード生成 できたっけ...? → v 1.10(※)から可能になりました

Slide 45

Slide 45 text

Code Generation(@turbo/gen) https://turbo.build/blog/turbo-1-10-0#code-generators

Slide 46

Slide 46 text

なぜモノレポ管理&ビルドツールに Code Generationが入った?

Slide 47

Slide 47 text

Nxを意識した説 Nxにもファイル・プロジェクト生成機能がある ・https://nx.dev/extending-nx/recipes/local-generators ・こちらが先発 ・JSON SchemaでCLIの引数などを定義できる ・ファイル構造を木として操作する ・競合としてTurborepoも実装することに(?) ・ユーザーからの要望は実際にあった

Slide 48

Slide 48 text

実は@turbo/gen、ほぼPlopです

Slide 49

Slide 49 text

@turbo/gen開発の経緯 2021/01 : 事の発端(※) ・https://twitter.com/jaredpalmer/status/1354886486265573377?s=20 ・Jared Palmer 氏が、Turborepoに合うGeneratorツールについて調べていた ・投票の結果、Turborepoに適したgeneratorにはPlopが選ばれた (本人もPlop推しの様子)

Slide 50

Slide 50 text

@turbo/gen開発の経緯 同年12月 : package/projectの追加方法についてのDiscussion ・https://github.com/vercel/turbo/discussions/243#discussioncomment-1860839 ・再び Jared Palmer 氏登場 ・Plopの使用をTurborepoのコミュニティ内でも提案 ・この後、IssueやDiscussionでちらほらPlopの言及が広がる(※)

Slide 51

Slide 51 text

@turbo/gen開発の経緯 翌年4月 : Code Generationに関してのIssue ・https://github.com/vercel/turbo/issues/4511 ・「複製することなく新たなプロジェクトを追加したい」ユーザーからの要望 ・後にCode Generationを実装する Thomas Knickman 氏による返答 ・このあたりから設計や実装が始まってそう

Slide 52

Slide 52 text

かれこれ1年ほどの構想を経て 2023/05にリリース

Slide 53

Slide 53 text

@turbo/genがほぼPlopなワケ →

Slide 54

Slide 54 text

@turbo/genがほぼPlopなワケ → コアコミッターたちの好み   (Nxより使いやすさを重視...?)

Slide 55

Slide 55 text

実装を見てみると よりPlopさを実感できるはずです https://github.com/vercel/turbo/tree/ main/packages/turbo-gen

Slide 56

Slide 56 text

CIUにおける活用方法の紹介

Slide 57

Slide 57 text

Docsの内容 + αで行っている 活用方法についてお話します

Slide 58

Slide 58 text

ディレクトリ構成 appやpackageとは分離して、/turbo 以下に集約 ・/turbo/config.ts : Plopの設定 ・/turbo/templates/**/*.hbs : Template

Slide 59

Slide 59 text

Generators (前提:Next.js App Routerのプロジェクト) ・components : UIコンポーネント ・pages : ページ(Page, Layout, Template) ・route-handlers : Route Handlers ・core-domain : 各種ドメイン(Controller, Entity, Presenter)層 ・core-schema : ZodによるSchema

Slide 60

Slide 60 text

Generators (前提:Next.js App Routerのプロジェクト) ・core-interface : Adapter(ClientとServerとの接続)層のInterface ・hooks-adapter : ↑の実装 ・hooks-usecase : Usecase層 ・hooks-cache-key-generator : SWRのキャッシュキー ・libs-locale : i18n対応用の辞書

Slide 61

Slide 61 text

Templates HandlebarsでGeneratorのTemplateを書く ・多くて数十行程度 ・百行までいくと流石に辛いので  超えるならTemplate化しない ・Templatesの仕様 ・PromptsのAnswerをReadできる ・case-modifiers

Slide 62

Slide 62 text

Prompts 所定の位置にファイルを置いて、その中に書く ・Promptsの仕様 ・配列形式でQuestionを記述できる ・関数を渡してInquirerのAPIをcallできる ・Inquirerのプラグインをそのまま使える ・inquirer-fuzzy-pathによる検索→

Slide 63

Slide 63 text

動作の様子

Slide 64

Slide 64 text

Actions Promptsと同様に書く ・Actionsの仕様 ・文字列にHandlebarsのSyntaxを使える ・配列形式でActionを記述できる ・関数を渡して条件分岐等もできる ・Templateを差し込む位置を  Answerによって変更→

Slide 65

Slide 65 text

動作の様子

Slide 66

Slide 66 text

所感・まとめ

Slide 67

Slide 67 text

所感 👍 スピード感を持って開発を進められるようになった ・新規が予定よりも早く、事故なく進行している ・外注はこれから ・コードの書き方は強制できるので、要件を伝えることに専念できる見込み 👍 configの書きやすさ ・JS分かれば読めて書ける ・HandlebarsのSyntaxで文字列の表現力が向上

Slide 68

Slide 68 text

所感 💭 HandlebarsとCLIの動作の遅さ ・Handlebarsの見づらさ、CLIの動作の遅さは課題 ・MD(MDX)だと、より人に優しいかも ・CLI部分だけでも脱JSできると速くなりそう ・Turborepo側で対応は今のところなさそう

Slide 69

Slide 69 text

今後の展望 Codemod Generatorでファイル更新の半自動化 ・Codemodを起動するGeneratorで更新に追従できるように Turborepoに乗っかり続ける vs Code Generator内製 ・当面はTurborepoを使い続けそうだが... ・Remote Cachingが求めていることに合うか次第 ・Code Generatorだけ使うなら内製しても良いかも ・Inquirerより速いCLI × Handlebars以外のDSL ・GoかRustで全部書く

Slide 70

Slide 70 text

ありがとうございました