JS/TSのプロジェクトで、ビルドシステムやmonorepoの構築に用いられるTurborepoには、Code Generationという機能が存在します。 この機能を活用した、人為的ミスの防止や開発リソースの削減など、実際にサイバーエージェントグループの開発現場で行われている取り組みについてお話します。
イベントURL:https://uit.connpass.com/event/291443/
Turborepo Code Generationによる、サイバーエージェントグループのフロントエンド開発の効率化UIT Meetup vol.20『これがぼくらのスタンダード』Shuta Hirai
View Slide
Shuta Hirai株式会社サイバーエージェント グループIT推進本部CyberAgent group Infrastructure Unit(CIU)フロントエンドエンジニアSocial Accounts・https://github.com/shuta13・https://twitter.com/did0es週末は代々木公園でフットサルをして、松屋で朝食を食べるのが僕のスタンダードです
1.CIUのフロントエンドについて2.開発における課題3.Code Generationによる開発の効率化4.CIUにおける活用方法の紹介5.所感・まとめ
CIUのフロントエンドについて
CIU:CyberAgent group Infrastructure Unit
CIU:サイバーエージェントグループのインフラ組織
プライベートクラウドやKaaS・IaaSなどのサービス開発、全社インフラの支援を行っています
CIUのフロントエンドの主な業務:
CIUのフロントエンドの主な業務:サービスの管理画面の開発
CIUの展開するサービス数
20
CIUのフロントエンドエンジニア数
2
開発における課題
①人手が足りない
サービス数 > 人数前述のとおり、サービス数に対して人手が足りていない・20個あるサービス全ての管理画面を作るわけではないが、それでも足りていない基本全てのフロントエンドを2人が見る状態・フロントエンドの設計・実装・運用全て2人で担当・さすがに全部は見きれないので、一部(20 - 30%程度)の実装は外注・マネジメント系のタスクも発生する
②コピペの多用
管理画面の例
似たような画面の開発社内向け管理画面・基本、新規が出る際は毎回似た構成の画面・提供したいものはあくまでCUIだったもののGUI版似ている → 使いまわせる・ドメインは違えど、ほとんどUIは変わらない・UI以外もほとんど変わらない・データ取得、アーキテクチャ、ディレクトリ構成etc…
ファイル数とコピペの問題使い回せるが故に、既存からコピペを繰り返す・数枚程度のファイルであれば良いが、数10 〜 100では...・人為的なミスが発生しうる可能性がどんどん上がるフロントエンドの構成上、ファイル数が増えがち・Clean Architecture によってデータ取得・更新の流れをわかりやすく・実装の見通しは良いが、その分ファイル数がかさむ・コピペしていては腱鞘炎になりかねない
③外部のコードの混在
外注の話・はじめに要件を提示して、成果物を貰う方式・密に連携が取れるわけではない・どうしてもレビューにラグが生じる・開発規約の変更があれば逐一共有する・なるべく揃えて、こちらで巻き取って修正はしないようにしたい・より機械的に、手数少なく共有できると◎
解決の方針:
解決の方針:開発の工数が少なく事故りにくく、外注もしやすい環境を実現する
ノーコードツールを使えば良いのでは?
🙅(not for us)
我々はエンジニア技術的挑戦の機会を捨てたくはない・エンジニアがいない組織ではない・自分たちの成長の機会も必要仮にノーコードツールを選定したとして・メンテは必要・サービスによって生成物を柔軟に変えられない(ことが多い)・結局コードをいじることになる
プロジェクトのtemplateを作れば良いのでは?
🙆(good)
プロジェクトのtemplateを作る場合コピペしなくてよくなる・CUI・GUIで画面を生成できる・生成したコードを変更してリリースコード自体がExampleの役割を担える・生成したコードを見れば、実装の方針がある程度わかるtemplate自体のメンテは必要・依存パッケージの更新、バグ修正など・雛形から作ったサービスの更新も必要
ファイルのtemplateを作れば良いのでは?
🙆🙆(great)
Code Generationによる開発の効率化
ファイルのtemplateを作る場合コピペしなくてよくなる・規約で縛れる・プロジェクトのtemplateと同様依存パッケージの更新など、重いメンテは必要なくなる・templateの更新だけで済む・影響範囲を絞れる・ダブルメンテ感は減る・書き方が変わった箇所は、grepして修正・(頑張れば)自動化もできる
(再掲)解決の方針:開発の工数が少なく事故りにくく、外注もしやすい環境を実現する
解決方法の整理開発の工数が少ない状態→ 必要なファイルを既存から人力で探すのではなく、CLIでtemplateから生成事故りにくい状態→ コピペしない templateは常に正しいものにする外注しやすい状態→ CLIの使い方だけ説明すれば、規約通りに実装が進められるようにする
解決手段 : Code Generationコードの自動生成・CLIの引数とtemplateから、コードを吐き出す自動生成向けツールの例・Plop: https://plopjs.com・Yoeman: https://yeoman.io・Hygen: https://www.hygen.io
ところで、
ところで、CIUではTurborepoを利用しています
なぜTurborepoなのかLernaからの移行・LernaをTurborepo + lerna-liteに置き換えたのがきっかけ・Lernaほど大きなものは我々には不要だった・publishはYarnやlerna-liteで賄えるTurborepoを選んだ背景・モノレポ管理 + α・ビルドシステムの整備・@turbo/gen
なぜTurborepoなのか@turbo/gen・packageやprojectをCLIから作成できる、コード自動生成ツール・基本は、既存のpackageのコピペをCLIで行う形・templateからの生成も可能・JSとHandlebarsで書く・拡張性◎で直感的・InquirerやPlopのAPIを使える
Turborepoって昔からコード生成できたっけ...?
Turborepoって昔からコード生成できたっけ...?→ v 1.10(※)から可能になりました
Code Generation(@turbo/gen)https://turbo.build/blog/turbo-1-10-0#code-generators
なぜモノレポ管理&ビルドツールにCode Generationが入った?
Nxを意識した説Nxにもファイル・プロジェクト生成機能がある・https://nx.dev/extending-nx/recipes/local-generators・こちらが先発・JSON SchemaでCLIの引数などを定義できる・ファイル構造を木として操作する・競合としてTurborepoも実装することに(?)・ユーザーからの要望は実際にあった
実は@turbo/gen、ほぼPlopです
@turbo/gen開発の経緯2021/01 : 事の発端(※)・https://twitter.com/jaredpalmer/status/1354886486265573377?s=20・Jared Palmer 氏が、Turborepoに合うGeneratorツールについて調べていた・投票の結果、Turborepoに適したgeneratorにはPlopが選ばれた(本人もPlop推しの様子)
@turbo/gen開発の経緯同年12月 : package/projectの追加方法についてのDiscussion・https://github.com/vercel/turbo/discussions/243#discussioncomment-1860839・再び Jared Palmer 氏登場・Plopの使用をTurborepoのコミュニティ内でも提案・この後、IssueやDiscussionでちらほらPlopの言及が広がる(※)
@turbo/gen開発の経緯翌年4月 : Code Generationに関してのIssue・https://github.com/vercel/turbo/issues/4511・「複製することなく新たなプロジェクトを追加したい」ユーザーからの要望・後にCode Generationを実装する Thomas Knickman 氏による返答・このあたりから設計や実装が始まってそう
かれこれ1年ほどの構想を経て2023/05にリリース
@turbo/genがほぼPlopなワケ→
@turbo/genがほぼPlopなワケ→ コアコミッターたちの好み (Nxより使いやすさを重視...?)
実装を見てみるとよりPlopさを実感できるはずですhttps://github.com/vercel/turbo/tree/main/packages/turbo-gen
CIUにおける活用方法の紹介
Docsの内容 + αで行っている活用方法についてお話します
ディレクトリ構成appやpackageとは分離して、/turbo 以下に集約・/turbo/config.ts : Plopの設定・/turbo/templates/**/*.hbs : Template
Generators(前提:Next.js App Routerのプロジェクト)・components : UIコンポーネント・pages : ページ(Page, Layout, Template)・route-handlers : Route Handlers・core-domain : 各種ドメイン(Controller, Entity, Presenter)層・core-schema : ZodによるSchema
Generators(前提:Next.js App Routerのプロジェクト)・core-interface : Adapter(ClientとServerとの接続)層のInterface・hooks-adapter : ↑の実装・hooks-usecase : Usecase層・hooks-cache-key-generator : SWRのキャッシュキー・libs-locale : i18n対応用の辞書
TemplatesHandlebarsでGeneratorのTemplateを書く・多くて数十行程度・百行までいくと流石に辛いので 超えるならTemplate化しない・Templatesの仕様・PromptsのAnswerをReadできる・case-modifiers
Prompts所定の位置にファイルを置いて、その中に書く・Promptsの仕様・配列形式でQuestionを記述できる・関数を渡してInquirerのAPIをcallできる・Inquirerのプラグインをそのまま使える・inquirer-fuzzy-pathによる検索→
動作の様子
ActionsPromptsと同様に書く・Actionsの仕様・文字列にHandlebarsのSyntaxを使える・配列形式でActionを記述できる・関数を渡して条件分岐等もできる・Templateを差し込む位置を Answerによって変更→
所感・まとめ
所感👍 スピード感を持って開発を進められるようになった・新規が予定よりも早く、事故なく進行している・外注はこれから・コードの書き方は強制できるので、要件を伝えることに専念できる見込み👍 configの書きやすさ・JS分かれば読めて書ける・HandlebarsのSyntaxで文字列の表現力が向上
所感💭 HandlebarsとCLIの動作の遅さ・Handlebarsの見づらさ、CLIの動作の遅さは課題・MD(MDX)だと、より人に優しいかも・CLI部分だけでも脱JSできると速くなりそう・Turborepo側で対応は今のところなさそう
今後の展望Codemod Generatorでファイル更新の半自動化・Codemodを起動するGeneratorで更新に追従できるようにTurborepoに乗っかり続ける vs Code Generator内製・当面はTurborepoを使い続けそうだが...・Remote Cachingが求めていることに合うか次第・Code Generatorだけ使うなら内製しても良いかも・Inquirerより速いCLI × Handlebars以外のDSL・GoかRustで全部書く
ありがとうございました