Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

0→1 フロントエンド開発 Tips🚀

0→1 フロントエンド開発 Tips🚀

2025年12月23日(火)に開催された、「レバテックMeetup~2025年のフロントエンド~」にて弁護士ドットコム株式会社 クラウドサイン エンジニアの辻佳佑が登壇した際の資料です。

セッションタイトル: 0→1 フロントエンド開発 Tips
https://levtechcareer.connpass.com/event/378105/

■ 弁護士ドットコム株式会社プロダクト組織について
https://docs.google.com/presentation/d/e/2PACX-1vTU9deZRyvMZDDrTgGC5Ns349IysFMwoGvJdAbIrrmDJ78Dbcfv8z0f2tjAG4M2E-Mn7YOdRlhb5Rt0/embed

■ 採用情報はこちら
https://hrmos.co/pages/bengo4/jobs

■ テックブログ:弁護士ドットコム Creators’ blog
https://creators.bengo4.com/

■ X(Twitter):弁護士ドットコム CREATOR'S
https://x.com/bengo4_creators

Avatar for 弁護士ドットコム

弁護士ドットコム

December 23, 2025
Tweet

More Decks by 弁護士ドットコム

Other Decks in Programming

Transcript

  1. Bengo4.com, Inc. 6 フレームワーク選定 Nuxt + TypeScript • Vueで構築されているデザインシステムを使いたい •

    開発に関わるエンジニアのスキルセットと相性がよい (バックエンドは Go)
  2. Bengo4.com, Inc. 8 従来の開発の苦労 • バックエンド、フロントエンドで APIの仕様をそれぞれ理解して、別々に実装する 必要がある ◦ リクエスト/レスポンスの型

    ◦ バリデーションルール ◦ エンドポイントのパス • バックエンドとフロントエンドで別々に仕様を定義する → つまり、二度手間 • どちらかの仕様変更漏れや認識のズレがバグを生むことも
  3. 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 ); }
  4. 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]", // });
  5. 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
  6. Bengo4.com, Inc. 14 静的解析における基本的な方針 原則: 厳しい設定でエラーを検知 • 後から厳しく設定するのは難しいため、最初に厳しくしておく • 厳しいルールへの対応が、エンジニアのレベル問わず

    AIの使用で可能になった 狙い: 以下の3つ 1. 安全なコードを書くこと 2. 一貫性のあるコードベースを保つこと 3. 実装者/レビュアーが本当に着目すべきコードの内容に集中して向き合えるようにす ること
  7. Bengo4.com, Inc. • 600個超のルールを導入 ◦ ルールセット antfu/eslint-config も含む ▪ 参考:

    https://github.com/antfu/eslint-config ◦ 各種プラグインの recommended なルールと、一部 strict なルールを導入 • カスタムルールは必要に応じて随時追加 ◦ 例: 破壊的なメソッド禁止、 jsdoc の記述強制、パスエイリアス /相対パスの使 い分けの強制 、特定のコンポーネント設置の強制、など ◦ TDDでAIに書かせる 15 ESLint
  8. 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
  9. Bengo4.com, Inc. 21 pages ┗ user-list   ┗ index.vue ユーザー一覧ページ

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

    ┃ ┗ UserRegisterDialog.vue ユーザー登録ダイアログ(一覧ページ専用)   ┗ index.vue ユーザー一覧ページ 共通コンポーネントだけを管理する ⚠Nuxtではpages/のコンポーネントはルーティングに含まれてしまうので含めない設定が別途必要 コロケーションで管理できている例( Nuxt)  
  11. Bengo4.com, Inc. 以下を両立させたいと考えた。 • 兄弟コンポーネント間において、グローバルステートを使ったデータの受け渡し とイベントバスは原則禁止 ◦ データやイベントの流れを追いやすくするため ◦ データを受け渡したり、イベントを検知させたい場合は、親子コンポーネント

    で受け渡せる関係にする • 共通レイアウトは layouts/ ディレクトリで管理する (Nuxt) ◦ レイアウト用コンポーネントをページごとに配置する運用は、配置忘れによる 意図しない実装が発生する恐れがあるため 25 ページレイアウト設計
  12. Bengo4.com, Inc. 26 よくあるレイアウト例 global header sidebar main header main

    content よくある以下のレイアウトを例にして説明する。 main
  13. Bengo4.com, Inc. 27 レイアウトの責務の確認 global header ログインユーザーの情報を表示 sidebar リンクを設置 し、パスパラ

    メータを操作 main header タイトル表示、メインコンテンツの操作 main content ページで見せたいコンテンツの表示 コンポーネントの責務をエンジニアとデザイナーで認識合わせ。 main
  14. Bengo4.com, Inc. 28 layouts/ で管理するレイアウトの決定 global header ログインユーザーの情報を表示 sidebar リンクを設置

    し、パスパラ メータを操作 main header タイトル表示、メインコンテンツの操作 main content ページで見せたいコンテンツの表示 以下の色分けでレイアウトを組むと、兄弟間でデータ、イベントの受け渡しが不要だと整理。 main main content とのレイアウトを layouts/ で区切ると グローバルステートやイベントバスが発生する
  15. Bengo4.com, Inc. 29 layouts/default.vue <template> <div class="Layout"> <LayoutHeader /> <div

    class="Layout-body"> <LayoutSidebar :component="sidebarComponent " /> <slot /> </div> </div> </template> layouts/default.vue の実装例。(このレイア ウトはページ毎に自動適用される) Sidebarのコンポーネントの内容は main (slotしたページコンポーネント)からメタ情報 (definePageMeta)として渡す。
  16. Bengo4.com, Inc. 30 子レイアウト global header ログインユーザーの情報を表示 sidebar リンクを設置 し、パスパラ

    メータを操作 main header タイトル表示、メインコンテンツの操作 main content ページで見せたいコンテンツの表示 main 内のレイアウトも共通のレイアウトを設定したい。 main
  17. Bengo4.com, Inc. 31 pages/index.vue <template> <MainLayout headerTitle="ユーザー一覧" :headerContents > <!--

    main content --> </MainLayout> </template> pages/ 以下にある index.vue コンポーネン トの template 直下に MainLayout を設置す ることをESLintのカスタムルールで強制。 同一ページに配置されているのでイベントバ スやグローバルな状態管理は不要。 template直下に設置され ていないとリントエラー
  18. 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 メソッドの 実装が壊れていてもテストで検知できないな どの問題が発生する。
  19. 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 へリクエストする限りテ ス ト自体は壊れず、堅牢になる。
  20. Bengo4.com, Inc. 36 StorybookでMSWを使う MSWで作ったモック定義は、テストだけでなく Storybookでも流用できる。 msw-storybook-addon を導入することで利用可能。 これにより、API リクエストの

    成功ケース・エラーケースなど 実アプリで起こりうる様々な 状態をStoryとして再現できる。 その結果、バックエンドの開発に依存しない、安定したフロントエンド開発・デザインレ ビュー環境を実現できる。 参考: https://github.com/mswjs/msw-storybook-addon
  21. Bengo4.com, Inc. 39 まとめ • 実装者の認知負荷を減らす設計と開発基盤を構築しよう ◦ Connect RPCを採用することで、型安全かつパスやHTTPメソッドを意識しない実装を実現でき る

    ◦ 静的解析や設計で実装の自由度を下げることで、コーディングの精度を向上できる ◦ 結果として、レビュー負荷が低減できる • フロントエンド開発を独立して進めるための仕組みを作ろう ◦ スキーマ駆動開発により、.protoさえ作成できればフロントエンド開発を開始、完了できる環境 を構築できる ◦ MSWを導入してAPI通信をモック化することで以下ができる ▪ ブラウザ上でのAPI通信の成功ケース・エラーケースの再現 ▪ 本番に近いテスト実施
  22. Bengo4.com,Inc. VISION まだないやり方で、世界を前へ。 Drive a paradigm shift for the better

    world. MISSION 「プロフェッショナル・テック 」で、次の常識をつくる。 Be the Professional-Tech Company. プロフェッショナルだからできること。専門知とテクノロジーで、社会に貢献する。
  23. Bengo4.com, Inc. OUR SERVICE 最新の法改正や実務について分かりやすく解説する 日本最大級の企業法務ポータルサイト 日本最大級の無料法律相談ポータルサイト 税理士に無料で相談・検索できる日本最大級の 税務相談ポータルサイト 時事問題の弁護士解説を中心としたメディア

    弁護士事務所、企業法務職向け人材紹介事業 契約の締結から管理までデジタルで完結させる 契約マネジメントプラットフォーム AI基盤技術「 LegalBrain 1.0」を組み込んだ リーガル特化型 AIエージェント