Slide 1

Slide 1 text

Vue Fes Japan 2026 Vue.jsのGitHubから学ぶ意思決定 Yuto NAGAI/Future & CodeCamp 2026/10/24 #vuefes #vuefes_medpeer

Slide 2

Slide 2 text

⾃⼰紹介 永井 優⽃/Yuto NAGAI フューチャーアーキテクト株式会社 シニアコンサルタント コードキャンプ株式会社 PdM(兼務出向) ‧北海道⼤学 公共政策⼤学院卒。部活はESSと⽇本語ディベート ‧2017年、IT未経験でフューチャーに新卒⼊社 ‧流通系やヘルスケア、国の医療DX案件を経て、現在は社内のAI推進、 新⼈研修の⽀援、CodeCampでエンジニアリング教育事業 X‧GitHub @yut0naga1 社外では ‧法政⼤学法学部 ⾮常勤講師、TSKaigi運営 ‧全⽇本ディベート連盟 マネージャー #Vue #TypeScript #競技ディベート #中⼩企業診断⼠ #⽇本BBQ協会認定BBQインストラクター #vuefes #vuefes_medpeer

Slide 3

Slide 3 text

今⽇話すこと‧話さないこと 記録に書かれた事実と、私の解釈を分けて話す 話すこと 話さないこと ‧ 問題‧候補‧制約‧決定を ‧ Vueの公式な歴史 たどる読み⽅ ‧ どこで提案が変わったか 事実 記録に書かれたこと 解釈 そこから私が考えたこと ‧ 「開発チームは内⼼こう考えていた」 という断定 話し⼿はコミッターではなく、 ⼀⼈のVueユーザー #vuefes #vuefes_medpeer

Slide 4

Slide 4 text

AIが書いてくれる今、何を学ぶか? 「書かなくていい」は「知らなくていい」ではない 実装の⼒は、良し悪しの判断に使う AIで速くなったこと 実装‧テスト‧修正 ⼈に残ること 理解し、疑い、⽐べ、直し、採⽤を決める 判断する‧意思決定 #vuefes #vuefes_medpeer

Slide 5

Slide 5 text

判断する⼒は、どこで⾝につける? 判断する⼒は、npm installできない $ npm i 判断力 npm error code E404 npm error 404 Not Found - GET https://registry.npmjs.org/判断力 - Not found npm error 404 npm error 404 '判断力@*' is not in this registry. npm error 404 npm error 404 Note that you can also install from a npm error 404 tarball, folder, http url, or git url. #vuefes #vuefes_medpeer

Slide 6

Slide 6 text

判断する⼒は、どこで⾝につける? 書いて失敗する途中は、ショートカットされやすい だから、先⼈の判断の記録から学ぶ ⼀つ⽬の道 書いて鍛える AIを使わない練習期間をつくる ただ、書く機会が減るほど、新⼈がつらい ⼆つ⽬の道 先⼈の判断から学ぶ ⽐べて選んだ記録を読む #vuefes #vuefes_medpeer

Slide 7

Slide 7 text

意思決定は、どんな順序で進むか? 案を⽐べて議論するなかで、よりよい案が出てくる その積み重ねで、いちばんよい案を選ぶ 課題 困っていることを ⾔葉にする 案を出す → A案‧B案…… 現状維持も案の⼀つ ⽐べて議論する → メリットと 選ぶ → デメリットを⽐べる いちばんよい 案を選ぶ 議論のなかで、C案やBの改案B’が出てくる よりよい案が積み重なっていく 甲⼄つけがたいトレードオフでは、何を判断軸にしたかまで読みたい このあとのCaseも、この枠組みで⾒ます #vuefes #vuefes_medpeer

Slide 8

Slide 8 text

決まるまでの途中経過は、どこに残っているか? GitHubのIssue‧PR‧RFCに、決まるまでの会話が残っている Issue ⇄ PR 利⽤者や開発者の 困りごと ⇄ RFC Pull Request Request for Comments 変更案と、そのレビュー 意⾒を求める設計提案。 問題設定‧代案‧ 採⽤案が書かれる 完成したAPIが答えそのもの、 GitHubの議論は答えに⾄るまでの過程 私はこっちを⾒たい。 #vuefes #vuefes_medpeer

Slide 9

Slide 9 text

3リポジトリ‧10年以上‧25,403件の記録を集めた 25,403件 3リポジトリ vuejs/vue Vue 2の実装 vuejs/core Vue 3以降の実装 vuejs/rfcs 設計提案 Issue‧PR‧RFCを収集 10年以上 対象期間 出所:GitHub vuejs/vue‧vuejs/core‧vuejs/rfcsの公開記録を筆者が収集‧集計 #vuefes #vuefes_medpeer

Slide 10

Slide 10 text

_⼈⼈⼈⼈⼈⼈_ > 25,403件 <  ̄Y^Y^YY^Y^Y ̄ 出所:GitHub vuejs/vue‧vuejs/core‧vuejs/rfcsの公開記録を筆者が収集‧集計 #vuefes #vuefes_medpeer

Slide 11

Slide 11 text

25,403件を、どこから読み始めるか? 数えられる情報だけで順位をつけ、読む順番を決める 25,403件 すべてを順番には 読めない 数えて採点 → 数えられる 先に読む候補 → 情報だけを使う ランクで 並べる 原⽂を開く → 中⾝はここで 確かめる 順位は、歴史的な重要度そのものではない 9位 core #9162 style: update format & lint config 整形ルールの変更 40位 rfcs #222 New script setup and ref sugar 後半で⽋かせない記録 出所:筆者集計の中⽴ランキング(output/11_score_comparison.md) #vuefes #vuefes_medpeer

Slide 12

Slide 12 text

採点では、何を⾒て、何を⾒ないか? Issue‧PRで主に⾒るのは、議論の量‧変更の広さ‧決定とのつながり ⾒る ⾒ない 議論の量 変更の広さ 決定とのつながり コメント‧レビューの数 変更ファイル数‧⾏数 マージ‧参照‧ (上限あり) リリースとの近さ ラベル AIによる内容評価 テーマ語 Composition API、 TypeScriptなど 読みたい結論に都合よく順位を作らないため。 件数はln(1+件数)で圧縮する 注:参照数はIssue‧PRの番号だけで数え、参照先のリポジトリを区別しない。順位は読む順番の⽬安で、重要度の尺度ではない(配点は13枚⽬) #vuefes #vuefes_medpeer

Slide 13

Slide 13 text

議論の件数が少ないRFCはどう取り扱う? RFC本⽂には基礎点を置き、議論が少なくても候補に残す 基礎点 + 本⽂の⻑さ + リンク数 RFC本⽂であること ⻑いほど良い、 本⽂内のGitHubリンク。 ⾃体に点を置く という意味ではない 関連記録をたどれる⽬安 配点に決まった正解はない。 だから採点スクリプトに、項⽬‧数値‧理由も吐かせる。 最後は⼈が原⽂で確かめる。 #vuefes #vuefes_medpeer

Slide 14

Slide 14 text

参考|採点の配点 Issue‧PRは10項⽬、RFC本⽂は3項⽬ 配点は読む順番を決めるための⽬安 Issue‧PR(n=件数) RFC本⽂ コメント数 4.5 × ln(1+n) 基礎点 +22 レビュー+レビューコメント数 5 × ln(1+n) 本⽂の⽂字数 1.5 × ln(1+文字数) 変更ファイル数(PR) 4 × ln(1+n) GitHubリンク数 1件につき +2 追加+削除⾏数(PR) 2 × ln(1+n)、上限20 マージ済み(PR) +7 vuejs/rfcsのPR +12 マイルストーンあり +4 他の記録からの参照数 7 × ln(1+n) リリース⽇との近さ 3日以内 +8/14日 +5/30日 +2 状態変化‧参照のイベント数 3 × ln(1+n)、上限12 #vuefes #vuefes_medpeer

Slide 15

Slide 15 text

上位5件の結果 上位5件は「公開API」と「内部実装」に分かれた 1 rfcs #42 Function-based API 106.36 公開API 2 core #5912 リアクティビティ効率化 103.84 内部実装 3 core #2345 effectの性能‧メモリ 81.70 内部実装 4 rfcs #182 SFC Improvements 81.66 公開API 5 core #10397 リアクティビティ再設計 80.38 内部実装 公開API:利⽤者に⾒えるAPIの形。今⽇はこちらを読む 内部実装:リアクティビティ‧性能‧メモリ 注:スコアの差は記録の量とつながりの差で、技術の優劣ではない #vuefes #vuefes_medpeer

Slide 16

Slide 16 text

公開APIのうち、どの記録を主役にする? 13位の#78を主役にする 上位の#42‧#182‧#227と同じ課題でつながって⾒える #42 1位 #227 Function-based API #182 8位 #17 30位 Class API(⾒送り) 4位 SFC Improvements #78 13位 Composition API 上位10件 事実 中⽴ランキングの上位10件に、#42‧#182‧#227の3件が⼊る 解釈 #78も含め、機能ごとの整理を選び、SFCで書きやすくするまでを追える。 採⽤案と不採⽤案を⽐べられる 出所:筆者集計の中⽴ランキング(output/11_score_comparison.md) #vuefes #vuefes_medpeer

Slide 17

Slide 17 text

Caseの⾒取り図 Options APIからまで六段階でたどる 1 2 3 Options API 問題 Class API案 出発点 RFC 0013 今も使える 4 5 6 Function- Composition <script based API案 API setup> #17 #42 #78 #182 → #227 不採⽤ #78へ改訂 採⽤ #227で採⽤ Composition API:状態や処理を機能ごとにまとめる、Vue 3で導⼊されたAPI <script setup>:Composition APIを.vueファイルで書きやすくした仕組み #vuefes #vuefes_medpeer

Slide 18

Slide 18 text

Options APIでは、カウンターをどう書くか? 状態‧計算‧更新を、役割ごとの箱に分けて書く ボタンで数を増やし、2倍も表⽰する export default { data() { return { count: 0 } }, computed: { doubled() { return this.count * 2 } }, methods: { increment() { this.count++ } } } data 状態 computed 計算値 methods 更新 どこに何を書くかが決まり、 初めて読む⼈も迷いにくい count に関わるコードは 三か所に分かれる #vuefes #vuefes_medpeer

Slide 19

Slide 19 text

Composition APIでは、同じカウンターをどう書くか? 同じ機能の状態‧計算‧更新を、近くにまとめて書ける import { ref, computed } from 'vue' export default { setup() { const count = ref(0) const doubled = computed(() => count.value * 2) function increment() { count.value++ } return { count, doubled, increment } } } count のコードを ⼀か所で読める Options APIが悪くなったわけではない。⼩さい部品では今も読みやすい #vuefes #vuefes_medpeer

Slide 20

Slide 20 text

Composition APIの出発点 コードが離れる、再利⽤しにくい、型を追いにくい、の三つ 1 コードが離れる 機能が増えるにつれ、⼀つの機能に関するコードが離れてしまう 2 再利⽤しにくい ロジックを別の部品で使い回すための、すっきりした仕組みがない 3 型を追いにくい TypeScriptが型を追いにくい → Class API‧Function-based API‧Composition APIがどう答えたかを⽐べる 出所:vuejs/rfcs RFC 0013「Composition API」Motivation #vuefes #vuefes_medpeer

Slide 21

Slide 21 text

案①:Class API 何を得ようとし、何に頼ったか? 型推論を狙ったが、propsの型は不確実なデコレータに頼った RFC #17の記法で書いたカウンター 事実 狙いは型推論と、 ネイティブのクラスで import Vue from 'vue' import { prop } from '@vue/decorators' 書けること RFC #17 Drawbacks class Counter extends Vue { @prop step: number count = 0 get doubled() { return this.count * 2 } increment() { this.count += this.step } } "It is thus still quite risky to design the API around decorators at this point." 解釈 注:記法(extends Vue‧ゲッター‧@prop)はRFC #17本⽂に基づく。Counter‧stepの例は説明⽤に作成 出所:vuejs/rfcs #17本⽂(class-apiブランチ) 何を前提に置くかも、 設計の選択だった #vuefes #vuefes_medpeer

Slide 22

Slide 22 text

案②:Function-based APIは、何を得ようとしたか? 機能ごとに関数へまとめ、別の部品で使い回す function useSearch() { const keyword = ref('') const results = ref([]) async function search() { results.value = await fetchResults(keyword.value) } return { keyword, results, search } } // 別の部品でも、同じ検索ロジックを使い回す const { keyword, results, search } = useSearch() 注:記法は現在のComposition APIに合わせた説明⽤の例 役割ごと data computed methods ↓ 機能ごと useSearch() usePagination() useForm() #vuefes #vuefes_medpeer

Slide 23

Slide 23 text

採⽤されたComposition APIは、既存の書き⽅をどう扱ったか? Options APIを置き換えず、並べて使える追加のAPIにした 事実 PR本⽂の冒頭 #42 Function-based API 冒頭のQ&A "Do I have to rewrite all my code?" → "No. ... purely additive" 既存のコードを全部書き直す必要はない。新しいAPIは純粋に追加的 #78 Composition API(#42の改訂版) 冒頭 "position the API as an advanced, additive API that works alongside existing API" 名前をComposition APIに変え、既存のAPIと並んで動く⾼度な追加APIと位置づけた 出所:vuejs/rfcs #42‧#78のPR本⽂(2026-10-05 原⽂確認) #vuefes #vuefes_medpeer

Slide 24

Slide 24 text

現状維持も⼊れて⽐べると、最終案は何を選んだか? 現状も残し、型推論と再利⽤の両⽅を狙ったように⾒える 案(記録をもとに整理) 狙い‧位置づけ 課題‧⾒直し 現状維持 書き換えが要らない RFC 0013の三つの課題が残る Class API 型推論。 デコレータへの依存 #17 ネイティブのクラスで書ける (⾒送り) Function-based API ロジックの整理‧再利⽤。 廃⽌の可能性の記述を、 #42 型推論も 利⽤者の声で削除 Composition API #42の改訂。 refと普通の値の区別。 #78 既存APIと並ぶ追加API ⾃由度に伴う規律 Options API 解釈 現状も残す。よりよい案にまとめたうえで、⽋点は記録の上受け⼊れた 出所:vuejs/rfcs #17本⽂、#42‧#78のPR本⽂、RFC 0013「Composition API」Motivation‧Drawbacks #vuefes #vuefes_medpeer

Slide 25

Slide 25 text

Composition APIを選んだあと、SFCで書くときに何が残ったか? テンプレートで使う値を毎回returnで返す⼿間が残っていた setup() { const count = ref(0) const increment = () => count.value++ return { count, increment } } const count = ref(0) const increment = () => count.value++ setup():最後にreturnで返す 値を⼀つ増やすたびに、 returnにも書き⾜す :returnは不要 トップレベルの値を、 テンプレートで直接使える 注:SFC(Single File Component)は画⾯‧状態‧スタイルを⼀つの.vueファイルに書く形式。両⽅ともimportは省略 #vuefes #vuefes_medpeer

Slide 26

Slide 26 text

は、最初の提案のまま決まったのか? 初期案は置き換えられ、 論点を分けた新しい提案がマージされた 1 2 3 #182 #222 #227 RFC 0040 SFC Improvements New script setup <script setup> #227の確定形 2020-06-29 作成 2020-11-09 クローズ and ref sugar 2020-11-09 作成 2021-07-01 マージ 冒頭に太字で、 2020-10-30 作成 2020-11-09 クローズ #222への置き換えを予告 ref sugarと ⼀緒に提案 4 #222から切り離し、 トップレベルの変数を、 単独で議論 テンプレートから 出所:vuejs/rfcs #182‧#222‧#227のPR本⽂、RFC 0040(スクリーンショットは2026-10-05撮影‧⽇付はUTC) 直接使える #vuefes #vuefes_medpeer

Slide 27

Slide 27 text

は、最初の提案のまま決まったのか? 初期案は置き換えられ、 論点を分けた新しい提案がマージされた #182 2020-06-29 → #222 2020-10-30 → #227 2020-11-09 → RFC 0040 #182 2020-11-09 クローズ この版の<script setup>は、 #222の新しい版に 置き換えられる、と 太字で書かれている 出所:vuejs/rfcs #182‧#222‧#227のPR本⽂、RFC 0040(スクリーンショットは2026-10-05撮影‧⽇付はUTC) #vuefes #vuefes_medpeer

Slide 28

Slide 28 text

は、最初の提案のまま決まったのか? 初期案は置き換えられ、 論点を分けた新しい提案がマージされた #182 2020-06-29 → #222 2020-10-30 → #227 2020-11-09 → RFC 0040 #222 2020-11-09 クローズ <script setup>と、 .valueなしでrefを使う 糖⾐構⽂を⼀緒に提案 出所:vuejs/rfcs #182‧#222‧#227のPR本⽂、RFC 0040(スクリーンショットは2026-10-05撮影‧⽇付はUTC) #vuefes #vuefes_medpeer

Slide 29

Slide 29 text

は、最初の提案のまま決まったのか? 初期案は置き換えられ、 論点を分けた新しい提案がマージされた #182 2020-06-29 → #222 2020-10-30 → #227 2020-11-09 → RFC 0040 #227 2021-07-01 マージ #222から <script setup>を 切り離して単独で議論する。 #222への フィードバックも反映 出所:vuejs/rfcs #182‧#222‧#227のPR本⽂、RFC 0040(スクリーンショットは2026-10-05撮影‧⽇付はUTC) #vuefes #vuefes_medpeer

Slide 30

Slide 30 text

は、最初の提案のまま決まったのか? 初期案は置き換えられ、 論点を分けた新しい提案がマージされた #182 2020-06-29 → #222 2020-10-30 → #227 2020-11-09 → RFC 0040 RFC 0040 #227がRFCとして残ったもの トップレベルの変数を テンプレートへ公開する、 新しいscriptの形 出所:vuejs/rfcs #182‧#222‧#227のPR本⽂、RFC 0040(スクリーンショットは2026-10-05撮影‧⽇付はUTC) #vuefes #vuefes_medpeer

Slide 31

Slide 31 text

は、最初の提案のまま決まったのか? 初期案は置き換えられ、 論点を分けた新しい提案がマージされた 1 2 3 #182 #222 #227 RFC 0040 SFC Improvements New script setup <script setup> #227の確定形 2020-06-29 作成 2020-11-09 クローズ and ref sugar 2020-11-09 作成 2021-07-01 マージ 冒頭に太字で、 2020-10-30 作成 2020-11-09 クローズ #222への置き換えを予告 ref sugarと ⼀緒に提案 解釈 4 #222から切り離し、 トップレベルの変数を、 単独で議論 テンプレートから 直接使える ⼀度出した案を置き換え、範囲を絞り直して前に進んだ 出所:vuejs/rfcs #182‧#222‧#227のPR本⽂、RFC 0040(スクリーンショットは2026-10-05撮影‧⽇付はUTC) #vuefes #vuefes_medpeer

Slide 32

Slide 32 text

参考|は、短く書くためだけの仕組みってこと? コンパイラが読む形式にして、短く書けて型も書きやすくした <script setup> 実⾏前にコンパイラが読む 変数を把握 → テンプレートの変数を知る 型を書きやすい → propsとイベントの型を 専⽤のマクロで書く <script setup lang="ts"> const props = defineProps<{ step: number }>() const emit = defineEmits<{ change: [value: number] }>() 出所:Vue公式ドキュメント API、RFC 0040(コード例はVue 3.3以降の記法) #vuefes #vuefes_medpeer

Slide 33

Slide 33 text

Caseから、どんな意思決定を学べたか? 答えだけでなく、決め⽅まで持ち帰れる 3 4 6 ⾒取り図の段階 記録に残っていた判断と、その根拠 Class API案 前提の危うさをもとに⾒送り #17‧RFC 0013 仕様が未確定のデコレータに頼る点を「リスクの⾼い前提」とした Function-based API案 OptionsAPIを置き換えず、両者を残した #42‧#78 新APIは「純粋に追加的」。廃⽌の記述は利⽤者の声を受けて削除 論点を分けて、前に進めた #227 SFC improvements およびref sugarと切り離し、<script setup>だけ を議論した 出所:RFC 0013、vuejs/rfcs #17‧#42‧#78‧#227の本⽂(2026-10-05 原⽂確認) #vuefes #vuefes_medpeer

Slide 34

Slide 34 text

次に使うOSSで試す、三つの⼿順 AIで読む順番を付け、読みたい記録を読み、関連する記録をたどる 1 AIを使って、読む優先度を付ける Issue‧PR‧RFCを集め、コメント数や参照数で並べる。 集めて並べるスクリプトは、AIと⼀緒に書ける 2 読みたいものを読む 順位は⼊⼝。上から順に読まなくてよい。 気になる問いに近い記録を選び、原⽂を開く 3 関連する記録を引っ張ってくる 本⽂のリンクや参照から、前後の提案をたどる。 AIにも探してもらい、最後は原⽂で事実と解釈を分ける #vuefes #vuefes_medpeer

Slide 35

Slide 35 text

この調査で、AIは何の役に⽴ったか? AIには決めさせず、次に読む記録を探す仕組みを⼀緒に作った AIが役に⽴ったこと ‧ 収集‧採点のスクリプトを ⼀緒に設計‧実装する ‧ 25,403件から、次に読む候補を 並べる⽅法を作る ⼈がやったこと ‧ 順位の限界を、⾃分で説明する ‧ 原⽂を読んで確かめる (AIの補助あり) ‧ 事実と解釈を分け、 何を選ぶかを決める #vuefes #vuefes_medpeer

Slide 36

Slide 36 text

クロージング 完成したAPIの裏にある 「決めるまで」を読む 不採⽤になった案も、消された⼀⽂も、 GitHubに残っている 次に使うOSSのGitHubで、Issue‧PR‧RFCを⼀つ開いてみてください。 ご清聴ありがとうございました #vuefes #vuefes_medpeer