Slide 1

Slide 1 text

Bengo4.com, Inc. 0→1フロントエンド開発 Tips🚀 2025.12.23 辻 佳佑

Slide 2

Slide 2 text

Bengo4.com, Inc. 辻 佳佑 Keisuke Tsuji フロントエンドエンジニア 弁護士ドットコム株式会社 < 趣味 > ボイトレ・ミシン < X アカウント > @t0daaay 2 自己紹介

Slide 3

Slide 3 text

Bengo4.com, Inc. 0→1フロントエンド開発の 技術選定、設計、開発基盤作り の実際の取り組みを紹介😎 3

Slide 4

Slide 4 text

前提 4

Slide 5

Slide 5 text

Bengo4.com, Inc. 5 実現したいこと 1. 開発速度を出す 2. コード品質を担保する 3. バグを極力出さない

Slide 6

Slide 6 text

Bengo4.com, Inc. 6 フレームワーク選定 Nuxt + TypeScript ● Vueで構築されているデザインシステムを使いたい ● 開発に関わるエンジニアのスキルセットと相性がよい (バックエンドは Go)

Slide 7

Slide 7 text

スキーマ駆動開発 7

Slide 8

Slide 8 text

Bengo4.com, Inc. 8 従来の開発の苦労 ● バックエンド、フロントエンドで APIの仕様をそれぞれ理解して、別々に実装する 必要がある ○ リクエスト/レスポンスの型 ○ バリデーションルール ○ エンドポイントのパス ● バックエンドとフロントエンドで別々に仕様を定義する → つまり、二度手間 ● どちらかの仕様変更漏れや認識のズレがバグを生むことも

Slide 9

Slide 9 text

Bengo4.com, Inc. 9 スキーマ駆動開発 スキーマを 信頼できる唯一の情報源 とする📃

Slide 10

Slide 10 text

Bengo4.com, Inc. 10 .proto によるスキーマ 定義とコード生成 スキーマ( .proto)に仕様を集約 リクエスト/レスポンスの型、サービス定義、バリデーションルール などを記述する buf を用いたコードの一括自動生成 buf で .proto ファイルから、BE・FE 双方のコードを生成できる syntax = "proto3" ; package user.v1; import "buf/validate/validate.proto" ; // ユーザー作成リクエスト message CreateUserRequest { // バリデーション(名前: 1〜50文字) string name = 1 [(buf.validate.field).string = { min_len: 1, max_len: 50, }]; // バリデーション(メール:必須 & email フォーマット) string email = 2 [(buf.validate.field).string = { email: true, }]; } // 作成されたユーザー message User { string id = 1; string name = 2; string email = 3; } // レスポンス message CreateUserResponse { User user = 1; } // ユーザーAPI service UserService { rpc CreateUser (CreateUserRequest ) returns (CreateUserResponse ); }

Slide 11

Slide 11 text

Bengo4.com, Inc. 11 生成コードを用いた Connect RPC 通信 Connect RPC による通信 ● ブラウザで動作する型安全な RPC ● .proto から生成したクライアントコードを呼ぶだけでサー バーにリクエスト可能 TanStack Queryで宣言的に扱う ● @connectrpc/connect-query を利用することで、RPC 呼び出しをTanstack Queryで効率的に扱える ○ ⚠connect-query はReact専用なので、 Vueでは connect-query-core と vue-query を組み合わせて実現 した // 以下は React の例 import { useMutation } from "@connectrpc/connect-query"; import { createUser } from "./gen/user/v1/user_connectquery"; const { mutate, data } = useMutation(createUser); // 実行例(ボタンクリック時などに呼び出し) // mutate({ // name: "Alice", // email: "[email protected]", // });

Slide 12

Slide 12 text

Bengo4.com, Inc. 12 構成図 TypeScript のコード APIクライアント & 型定義 Go のコード サーバーインターフェース & 構造体 コード生成 (buf generate) スキーマ定義 (.proto) 型安全なConnect RPC通信 protoc-gen-go protoc-gen-es protoc-gen- connect-query protoc-gen- connect-go (フロントエンド) (バックエンド) vue-query connect-query-core

Slide 13

Slide 13 text

静的解析 13

Slide 14

Slide 14 text

Bengo4.com, Inc. 14 静的解析における基本的な方針 原則: 厳しい設定でエラーを検知 ● 後から厳しく設定するのは難しいため、最初に厳しくしておく ● 厳しいルールへの対応が、エンジニアのレベル問わず AIの使用で可能になった 狙い: 以下の3つ 1. 安全なコードを書くこと 2. 一貫性のあるコードベースを保つこと 3. 実装者/レビュアーが本当に着目すべきコードの内容に集中して向き合えるようにす ること

Slide 15

Slide 15 text

Bengo4.com, Inc. ● 600個超のルールを導入 ○ ルールセット antfu/eslint-config も含む ■ 参考: https://github.com/antfu/eslint-config ○ 各種プラグインの recommended なルールと、一部 strict なルールを導入 ● カスタムルールは必要に応じて随時追加 ○ 例: 破壊的なメソッド禁止、 jsdoc の記述強制、パスエイリアス /相対パスの使 い分けの強制 、特定のコンポーネント設置の強制、など ○ TDDでAIに書かせる 15 ESLint

Slide 16

Slide 16 text

Bengo4.com, Inc. ● 基本的なルールセット ○ stylelint-config-standard, stylelint-config-recommended-vue ● SUIT CSSに沿った命名強制 ○ .Component {} , .Component-descendant {} , .Component--modifier {} のようなBEMに似た記法 ○ plugin/selector-bem-pattern とカスタムルールを組み合わせてシ ンプルな形で命名を統一しやすい点から、この記法を選定しリン ターで強制した ■ 参考: https://www.npmjs.com/package/stylelint-selector-bem-pattern 16 Stylelint

Slide 17

Slide 17 text

Bengo4.com, Inc. 17 Type Checking tsconfigのCompiler OptionsのType Checkingの全20項目 全てを厳しく設定。 参考: https://www.typescriptlang.org/tsconfig

Slide 18

Slide 18 text

Bengo4.com, Inc. 18 Knip 未使用ファイル、コード、ライブラリを検知できるライブラリ。 参考: https://knip.dev/

Slide 19

Slide 19 text

コロケーション 19

Slide 20

Slide 20 text

Bengo4.com, Inc. 20 コロケーションとは 関連するコードやファイルを、物理的に近い場所にまと めて配置するという設計思想。 関連するものをまとめることで、開発者の認知負荷を下 げ、変更・理解・スケールを楽にできる。

Slide 21

Slide 21 text

Bengo4.com, Inc. 21 pages ┗ user-list   ┗ index.vue ユーザー一覧ページ components ┗ user-list   ┗ UserRegisterDialog.vue ユーザー登録ダイアログ(一覧ページ専用) コロケーションで管理できていない例( Nuxt)  

Slide 22

Slide 22 text

Bengo4.com, Inc. 22 pages ┗ user-list   ┣ _components   ┃ ┗ UserRegisterDialog.vue ユーザー登録ダイアログ(一覧ページ専用)   ┗ index.vue ユーザー一覧ページ 共通コンポーネントだけを管理する ⚠Nuxtではpages/のコンポーネントはルーティングに含まれてしまうので含めない設定が別途必要 コロケーションで管理できている例( Nuxt)  

Slide 23

Slide 23 text

Bengo4.com, Inc. 23 コロケーションのコツ ディレクトリを削除時、依存関係にあるファイルが一緒に削除されるディレ クトリ構成になっているかを意識すると分かりやすい。

Slide 24

Slide 24 text

ページレイアウト設計 24

Slide 25

Slide 25 text

Bengo4.com, Inc. 以下を両立させたいと考えた。 ● 兄弟コンポーネント間において、グローバルステートを使ったデータの受け渡し とイベントバスは原則禁止 ○ データやイベントの流れを追いやすくするため ○ データを受け渡したり、イベントを検知させたい場合は、親子コンポーネント で受け渡せる関係にする ● 共通レイアウトは layouts/ ディレクトリで管理する (Nuxt) ○ レイアウト用コンポーネントをページごとに配置する運用は、配置忘れによる 意図しない実装が発生する恐れがあるため 25 ページレイアウト設計

Slide 26

Slide 26 text

Bengo4.com, Inc. 26 よくあるレイアウト例 global header sidebar main header main content よくある以下のレイアウトを例にして説明する。 main

Slide 27

Slide 27 text

Bengo4.com, Inc. 27 レイアウトの責務の確認 global header ログインユーザーの情報を表示 sidebar リンクを設置 し、パスパラ メータを操作 main header タイトル表示、メインコンテンツの操作 main content ページで見せたいコンテンツの表示 コンポーネントの責務をエンジニアとデザイナーで認識合わせ。 main

Slide 28

Slide 28 text

Bengo4.com, Inc. 28 layouts/ で管理するレイアウトの決定 global header ログインユーザーの情報を表示 sidebar リンクを設置 し、パスパラ メータを操作 main header タイトル表示、メインコンテンツの操作 main content ページで見せたいコンテンツの表示 以下の色分けでレイアウトを組むと、兄弟間でデータ、イベントの受け渡しが不要だと整理。 main main content とのレイアウトを layouts/ で区切ると グローバルステートやイベントバスが発生する

Slide 29

Slide 29 text

Bengo4.com, Inc. 29 layouts/default.vue
layouts/default.vue の実装例。(このレイア ウトはページ毎に自動適用される) Sidebarのコンポーネントの内容は main (slotしたページコンポーネント)からメタ情報 (definePageMeta)として渡す。

Slide 30

Slide 30 text

Bengo4.com, Inc. 30 子レイアウト global header ログインユーザーの情報を表示 sidebar リンクを設置 し、パスパラ メータを操作 main header タイトル表示、メインコンテンツの操作 main content ページで見せたいコンテンツの表示 main 内のレイアウトも共通のレイアウトを設定したい。 main

Slide 31

Slide 31 text

Bengo4.com, Inc. 31 pages/index.vue pages/ 以下にある index.vue コンポーネン トの template 直下に MainLayout を設置す ることをESLintのカスタムルールで強制。 同一ページに配置されているのでイベントバ スやグローバルな状態管理は不要。 template直下に設置され ていないとリントエラー

Slide 32

Slide 32 text

MSW 32

Slide 33

Slide 33 text

Bengo4.com, Inc. 33 MSW(Mock Service Worker)とは? API通信をモックできるツール。 ブラウザではService Worker、Node.jsでは独自の仕組み (msw/node)でHTTPリクエストをインターセプト(横取り)し、任意のレ スポンスを返す仮想のAPIサーバーを実現する。

Slide 34

Slide 34 text

Bengo4.com, Inc. 34 従来のテスト import { render, screen } from "@testing-library/vue"; import UserProfile from "./UserProfile.vue"; import * as api from "./api"; test("メソッドモックでユーザー名を表示", async () => { vi.spyOn(api, "fetchUser").mockResolvedValue({ name: "Taro" }); render(UserProfile); expect(await screen.findByText("こんにちは、Taro さ ん")).toBeInTheDocument(); }); 右の例では、APIリクエストのメソッド (fetchUser)をモック しており、HTTPリクエ スト周りの挙動を検証できない。 その結果、fetchUser メソッドの命名が変わ るとテストが壊れたり、 fetchUser メソッドの 実装が壊れていてもテストで検知できないな どの問題が発生する。

Slide 35

Slide 35 text

Bengo4.com, Inc. 35 MSWを使ったテスト import { render, screen } from "@testing-library/vue"; import UserProfile from "./UserProfile.vue"; import { setupServer } from "msw/node"; import { http, HttpResponse } from "msw"; const server = setupServer( http.get("/api/user", () => { return HttpResponse.json({ name: "Taro" }); }) ); beforeAll(() => server.listen()); afterEach(() => server.resetHandlers()); afterAll(() => server.close()); test("MSW で API をモックしてユーザー名を表示", async () => { render(UserProfile); expect(await screen.findByText("こんにちは、Taro さ ん")).toBeInTheDocument(); }); MSWでAPI通信をモックし、実際の APIに リクエストしているかのようにテストを実行 できる。 その結果、URLやレスポンス形式の誤りな ど、より現実に近いバグを検出しやすくな る。 また、APIリクエスト関数の命名や実装が変 わっても、/api/user へリクエストする限りテ ス ト自体は壊れず、堅牢になる。

Slide 36

Slide 36 text

Bengo4.com, Inc. 36 StorybookでMSWを使う MSWで作ったモック定義は、テストだけでなく Storybookでも流用できる。 msw-storybook-addon を導入することで利用可能。 これにより、API リクエストの 成功ケース・エラーケースなど 実アプリで起こりうる様々な 状態をStoryとして再現できる。 その結果、バックエンドの開発に依存しない、安定したフロントエンド開発・デザインレ ビュー環境を実現できる。 参考: https://github.com/mswjs/msw-storybook-addon

Slide 37

Slide 37 text

Bengo4.com, Inc. 37 例: 認証エラーのストーリー

Slide 38

Slide 38 text

まとめ 38

Slide 39

Slide 39 text

Bengo4.com, Inc. 39 まとめ ● 実装者の認知負荷を減らす設計と開発基盤を構築しよう ○ Connect RPCを採用することで、型安全かつパスやHTTPメソッドを意識しない実装を実現でき る ○ 静的解析や設計で実装の自由度を下げることで、コーディングの精度を向上できる ○ 結果として、レビュー負荷が低減できる ● フロントエンド開発を独立して進めるための仕組みを作ろう ○ スキーマ駆動開発により、.protoさえ作成できればフロントエンド開発を開始、完了できる環境 を構築できる ○ MSWを導入してAPI通信をモック化することで以下ができる ■ ブラウザ上でのAPI通信の成功ケース・エラーケースの再現 ■ 本番に近いテスト実施

Slide 40

Slide 40 text

Bengo4.com, Inc. ありがとうございました

Slide 41

Slide 41 text

Bengo4.com, Inc. We are Hiring

Slide 42

Slide 42 text

Bengo4.com,Inc. VISION まだないやり方で、世界を前へ。 Drive a paradigm shift for the better world. MISSION 「プロフェッショナル・テック 」で、次の常識をつくる。 Be the Professional-Tech Company. プロフェッショナルだからできること。専門知とテクノロジーで、社会に貢献する。

Slide 43

Slide 43 text

Bengo4.com, Inc. OUR SERVICE 最新の法改正や実務について分かりやすく解説する 日本最大級の企業法務ポータルサイト 日本最大級の無料法律相談ポータルサイト 税理士に無料で相談・検索できる日本最大級の 税務相談ポータルサイト 時事問題の弁護士解説を中心としたメディア 弁護士事務所、企業法務職向け人材紹介事業 契約の締結から管理までデジタルで完結させる 契約マネジメントプラットフォーム AI基盤技術「 LegalBrain 1.0」を組み込んだ リーガル特化型 AIエージェント