はじめに
Vue3のリリースが迫ってきました。
順調に行けば、公式リリースは8月上旬のようです。楽しみですね。
Our current target dates are mid July for the RC (release candidate) and early August for the official release of 3.0.
https://github.com/vuejs/rfcs/issues/183
Vue3の目玉の機能として、**「Composition API」**があります。
この記事では、**「”なぜ” “なんのために” Composition APIを使うのか」**理由について、まとめています。
「Composition APIの使い方」についての説明は、この記事では割愛します。
以下の記事に、具体的なComposition APIの使い方とProviderパターンについて記述しました。
本記事と合わせて御覧ください。
Vue3 Composition APIにおいて、Providerパターン(provide/inject)の使い方と、なぜ重要なのか、理解する。
https://qiita.com/karamage/items/4bc90f637487d3fcecf0
Composition APIを使う理由、なんもわからん
これまで、私自身、Composition APIを使う理由が、よくわかっていませんでした。
なんとなく、「setup関数でまとめて処理を登録しておく」くらいのことを雰囲気で理解していました。
「Composition APIで書くほうがイケてるし、カッコいい(重要)」くらいのノリで
何のために使うのか、メリットがよく分からない状態でした。
Composition APIについて調べていると、↑の図、よく見ませんか?
既存APIとComposition APIのコードを比較して、メリットを提示しているようですけど
私は
「そんなに違わないように見える」
「違いがよくわからん」
っといった感想を持ちました。
私と同じように
「Vueに新しく、Composition APIってのが出るらしいけど、なんとなく使おうかな〜」
「でも、なんのために使うんだっけ」
と思っている方が多いのではないかなと考え、この記事を執筆しています。
この記事が、誰かのお役に立てれば幸いです。
Composition API RFC を読んだら、「なぜ、使うのか」を理解した
先日 @shwld が主催した
「Vue Composition APIを知る会」
で、Composition APIのRFCを読む機会があり、そこで改めて「”なぜ” Composition APIを使うのか」理解することができました。
Composition APIの公式の説明資料として、以下のページにRFCがあります。
Composition API (https://vue-composition-api-rfc.netlify.com)
↑を読むと、「”なぜ” Composition APIを使うのか」答えが書いてありました。
以下にRFCに書いてある内容をまとめます。
Composition APIとは
Composition APIは、
ロジックを合成関数(composition function)にカプセル化することで、コンポーネント間でのロジックを再利用を可能にするAPIです。
(React HooksのVue版みたいなもの)
「Composition」は、**「構成(すること),組み立て(ること)」**という意味。
サンプルコード
<template>
<button @click="increment">
Count is: {{ state.count }}, double is: {{ state.double }}
</button>
</template>
<script>
import { reactive, computed } from 'vue'
export default {
setup() {
const state = reactive({
count: 0,
double: computed(() => state.count * 2)
})
function increment() {
state.count++
}
return {
state,
increment
}
}
}
</script>
Vueの作成者であるEvan You氏いわく、Composition APIを提案する背景となった動機について、次のように説明しています。
論理合成(logic composition)は、プロジェクトをスケールアップする場合には、おそらく最も深刻な問題のひとつです。さまざまなタイプのプロジェクトを扱うユーザは、さまざまなニーズに直面します。その中には、オブジェクトベースのAPIを使用して簡単に処理できるものと、できないものがあります。主な例としては、
- 複数の論理タスクをカプセル化した、大規模な(数百行の)コンポーネント
- 複数のコンポーネント間においてタスクにロジックを共有するニーズ
https://www.infoq.com/jp/news/2019/10/vue3-function-based-api-rfc/ より引用
”なぜ” Composition APIを使うのか
結論から言いますと、
「”なぜ” Composition APIを使うのか」
その理由は、
「ロジックの抽出と再利用」をするためです。
(他にも「TypeScript 型強化」などが理由として挙げられますが、この記事では割愛します)
ロジックの抽出と再利用
「ロジックの抽出と再利用」は、なぜするのか。
「ロジックの抽出と再利用」が必要な理由は、
複雑に肥大化したコンポーネントを、小分けにして関心事で分別し、クリーンな状態に整理するためです。
近年、Vue を使用して大規模なプロジェクトを構築することが増えました。
肥大化してメンテしにくいコンポーネントを目の当たりにして、我々エンジニアが苦しむことも増えました。
肥大化したコンポーネントのコードは、依存関係が複雑で量も多く、コードを読むこと自体難しくなります。
これまでのVue2.xでは、「複数のコンポーネント間でロジックを抽出して再利用するためのクリーンでコストのかからないメカニズム」が欠如していました。
Vue2.xでは、コンポーネントをSFCファイルに記述します。
SFCファイルに、コンポーネントのView/状態/ロジックをまとめて閉じ込めて記述することができて便利ですが、これ以上は分割ができないという欠点がありました。
これを解決するのが、Composition APIです。
Composition APIによって、コンポーネントのコードを整理する際に、開発者により高い柔軟性を提供します。
コンポーネント間で、ロジックや状態を抽出して再利用することが、簡単になります。
SFCに記述するのはViewの見た目に関することだけにして、ロジックや状態を外部に切り出せるようになるのです。
つまり、Composition APIは、肥大化したコンポーネントを小さく切り刻むための聖剣なのです。
Composition APIを使って「ロジックを抽出して再利用する」具体的なやり方について、以下の記事が参考になります。
vue-composition-apiを使って機能単位のコード分割と合成を試してみた
https://qiita.com/s_nagasawa/items/ef70032f996face318e5
逆に言えば、100行にも満たないような小さなコンポーネントをComposition APIで書き直しても、あまりメリットを享受できないです。
もし小規模〜中規模なVueプロジェクトにおいて、現状のVue2.xベースのコードでコンポーネントの肥大化に苦しんでいないのであれば、Composition APIで書き直してもコスパが悪いのでやめておいたほうがよいのではないかなと思います。
(新規プロダクトで、最初から全部Composition APIで書くのはありだと思います)
mixinは、使えない?
Vue2.xのロジックの再利用の仕組みとして、「mixin」があります。
しかし、「mixin」には、罠が多くあり、今では「mixin」を使うことはアンチパターンという認識です。
極力「mixin」は使わないようにしましょう。
なぜmixinがアンチパターンなのかについては、下記の記事に詳しく書かれてあります。
俺がやらかしたVue mixinのアンチパターンから学ぶmixinの使い方と代替案
https://aloerina01.github.io/blog/2018-12-25-1
Composition APIを使う際のデメリット
ここまでの説明で、Composition APIを使うメリットは、理解できたかと思います。
じゃあ、デメリットはないのか?
あります。
デメリットを一言でいうと、**「自由すぎ」**です。
Composition APIによって、自由にロジックを切り出せるようになりますが、一方で、いままでVueが暗黙的に行ってくれていたレールから外れることを意味します。
今までは、何となくコンポーネントをSFCファイルに記述して、状態管理をVuexに任せておけば、何とかなっていたのですが、それが根本からガラッと大幅に変わります。
Composition APIによって、Vueの世界と外の世界に任意の境界線を引き、モジュールに切り分けて、どれとどれを結合するかを、自由に「設計」できるようになります。
しかしながら、どういう単位でロジックやモジュールを切り出したり、共通化したり、といった疑問に対して、明確な正解がないのです。
Composition APIのベストプラクティスを今決めるのは時期尚早であり、手探りで進める必要があります。
つまり、Vueが管理している壁の中の世界から、壁の外の無秩序な荒野へと放り出されるのです。
無秩序な荒野で、テキトーに開発していると、隠れていた猛獣に襲われたり、食料が尽きたりといった致命的なアクシデントに見舞われます。計画的に外の世界を開拓しないと危険がいっぱいなのです。
人柱になりたくない方は、**「様子見」**という選択も、アリだと思います。
「設計」や「アーキテクチャ」が重要になる
その荒野に秩序を与えるのは、我々、調査兵団(エンジニア)の**「設計」**です。
今後は、**「アーキテクチャ」**が重要になります。
つまり、Composition APIを使用するデメリットは、ちゃんと「設計」や「アーキテクチャ」を考えなければならないことです。
学習コストも、高いです。
例えば、「クリーンアーキテクチャ」を理解して、実装していくことが求められます。
実装クリーンアーキテクチャ
https://qiita.com/nrslib/items/a5f902c4defc83bd46b8
「Vueの中の世界」と「外の世界」の境界線を意識して、自由への翼を獲得しましょう。
まとめ
・https://vue-composition-api-rfc.netlify.com を読もう。
・Composition APIを使う理由は、**「ロジックの抽出と再利用」**のため。(TypeScriptの型強化の側面もあり)
・肥大化したコンポーネントを、小さく切り刻むための聖剣だと理解した。(mixin、お前はダメだ)
・聖剣ですので、使いこなすには、それなりの熟練度が必要。レベル1の村人が装備すると怪我をする恐れもあり。
・もともと小さいコンポーネントをCompositon APIで書き直しても、あまりメリットはない。
・今後はちゃんと**「設計」や「アーキテクチャ」**を考えなければならない。
Composition API リンク集
Composition API RFC
https://vue-composition-api-rfc.netlify.com
API Reference
https://composition-api.vuejs.org/api.html
Composition API Demo
https://github.com/LinusBorg/composition-api-demos
vue-composition-apiを使って機能単位のコード分割と合成を試してみた
https://qiita.com/s_nagasawa/items/ef70032f996face318e5
俺がやらかしたVue mixinのアンチパターンから学ぶmixinの使い方と代替案
https://aloerina01.github.io/blog/2018-12-25-1
実装クリーンアーキテクチャ
https://qiita.com/nrslib/items/a5f902c4defc83bd46b8
【Vue3に備える】実務で使うComposition APIについて考える
https://medium.com/finatext/composition-api-for-vue3-63631dbadcef
先取りVue 3.x !! Composition API を試してみる
https://qiita.com/ryo2132/items/f055679e9974dbc3f977
Vue Composition API v1-beta で使えるリアクティブ関連のAPI一覧
https://qiita.com/ryo2132/items/6dc51ede8082dea75812
Vue Composition API を使ったストアパターンと TypeScript の組み合わせはどのくらいスケールするか?
https://qiita.com/tmy/items/a545e44100247c364a71
Composition API 勘所など
https://webneko.dev/posts/notices-of-composition-api-in-vue3-eve
Vue.jsのcomposition-apiにおける"ref"と"reactive"って何が違うの?
https://qiita.com/mgr/items/a5e35636d371969e0a4d
【Vue.js】Composition API時代の便利ライブラリ「VueUse」を使ってみた
https://qiita.com/mascii/items/558c7d5d5bf82eaa59a6