[6/8 12時頃追記]
Vueは死んでないし殺すつもりもないし私はVueが大好きだ、誤解しないでほしい
Vue3でOptions APIは消えてないし今後消えていく方向のAPIでもないし挫折した人もこっちつかって再挑戦してほしい
[6/8 11時頃追記]
「俺はComposition API使えてるぞ!」「便利じゃん!何をいってるんだこいつは!」
あなたはすごい、でもVueを挫折した人の話を聞くに、Composition APIが「アタリマエでしょ?」の雰囲気の前にうまく馴染めず散っていったという話で、Composition API自体は好きです
Vue3の衰退を招いたのは<script setup>かもしれないCompositionAPIという考察
ほとんど肌感であり、根拠のない妄言だと思ってもらって構わないのだが、Vue3のリリース以降Vueが流行から離れつつあり、その原因は<script setup>とcompotision APIにあるのではないかと考えるに至った。
その辺りを書き綴っていく
お前は誰なのか
Vue2系に魅せられて以来ずっとVueを仕事にしている。Nuxtも触ったし、Nuxt3にマイグレーションするプロジェクトに従事している。
今もVueが大好きだし、Reactはほぼ(意図的に)触ってないし今後もVueを仕事にするだろう
CompositionAPIとは
Vue3を設計するにあたり、「よりTypeScriptフレンドリーな」構文としてプロパティデコレータスタイルのRFCに変わって提唱されたRFCであり、実際に実装されたAPIでもある。
Options API に setup(props, context) { } という関数を渡すと、その中は Pure なJavaScriptであり this がコンポーネントを刺さず、かわりにsetup関数の引数からpropsやその他の項目にアクセスできる。これによって型が綺麗になったねやったね!
やったか? 型が綺麗になっただけでできること増えてないぞ?
「Compotision APIは上位互換の全く新しいAPI」という誤解
「Composition API使わないのは時代遅れ!!!ダサい!!!」みたいな感覚と実際の使いにくさが幾人もの初学者を葬り、Vue2からVue3へアップグレードを試みた者を葬ったという肌感がある
Composition API変わりすぎ!!!それぐらいならReactいくぞ!!!!って人が実際結構いるのではないかと感じているのだけど、それは悲しい誤解で、 Options APIを使い続けるので何も問題なかったのに……と私は思っている。そしてVue3でもOptions APIはそのまま使うことができる。
Composition APIは選択肢の一つであって、Options APIをメインに据えてもいいのだ
<script setup> と初期セットアップ
<script setup> とはマクロである
内部に書かれたものを setup関数の中身のようなものとしてよしなにやってくれる
<script setup>
import { ref, onMounted } from 'vue'
// リアクティブな状態
const count = ref(0)
// 状態を変更し更新トリガーする関数
function increment() {
count.value++
}
// ライフサイクルフック
onMounted(() => {
console.log(`The initial count is ${count.value}.`)
})
</script>
<template>
<button @click="increment">Count is: {{ count }}</button>
</template>
上記のコードはだいたい以下のようになる
<script>
import { ref, onMounted } from 'vue'
export default {
setup(){
// リアクティブな状態
const count = ref(0)
// 状態を変更し更新トリガーする関数
function increment() {
count.value++
}
// ライフサイクルフック
onMounted(() => {
console.log(`The initial count is ${count.value}.`)
})
return {
increment,
count
}
}
}
</script>
最終的にコンパイラによってマージされる
<script>
export default {
data(){
return { count: 0 }
},
methods: {
increment() {
this.count++
},
mounted(){
console.log(`The initial count is ${this.count}.`)
}
}
</script>
<script setup> の功罪
公式のスキャフォルドでいきなり出てくるな!
公式チュートリアルではOptions APIをベースに話が始まる。
ところが、 クイックスタートの> npm init vue@latest を実行すると、App.vue が <script setup> で作成されてしまう。
こうなると、Options APIのドキュメントはすべて意味をなさず、初学者の心をへし折ったのではないだろうか。
一癖も二癖もある ref と reactive
setup関数内ではリアクティブなデータは ref() または reactive() でラップして明示的にリアクティブにしなければならない。
そうでなければリアクティブな監視を行わないため、パフォーマンス向上につながる。
理屈はわかるのだが、 const hoge = ref("foo") としてつくると、 hoge.value = "piyo" というように、 .value というアクセサを使わないと書き込みができない。
const state = reactive({hoge: "foo"}) とすると、 state.hoge = "piyo" ができたかな。
なんか挙動に一貫性がない。そもそも2つあるのがよくわからない。
挙げ句スプレッド演算子を使うとunwrapされたりするし。
OptionsAPIのdata() メソッドがまとめてよしなにしてくれるのと比べるとどうも罠が多いような気がする
というかこの辺で詰まって初心者からVue3マイグレーションを試みた人たちを薙ぎ払っていったのではないか
Composition API と Options APIはテンプレートコンパイラ的には同じ
setup関数に書いてあることは、 beforeMountedライフサイクルの前で実行され、適切にOptions APIにマージされる。
TypeScriptの場合型定義上も問題ない。
あなた(筆者)はCompotision APIは使わないのか?
<script setup> にはあまり魅力を感じないが、 setup() を用いたComposition APIを部分的に採用することがある。
先述の通り、適切にマージされるので、基本的にOptions APIで書いて、 VueUseを使いたいのでそこだけ setup 関数の中に書いておくみたいなことが可能である。
備考:
setup 関数の中にあるものは OptionsAPIから参照できるが、OptionsAPIの中にあるものはsetup関数の中から参照できない
結論
せっかく「わかりやすいVue」という路線で人を集めていたのに、script setupの登場で台無しになってしまった感がある。
そして数多のVueを志した人たちの首を刈り取ったのではないか。
Evanも言っていたではないか、「Composition APIは複雑なコンポーネントを整頓するのに役立てるAPIである一方で、考えなしに使うと余計な混乱を招く」「Vue3のOptions APIで満足しきれなかった人のためのComposition APIなのだ」と……出典がどこなのか全くわからないし記憶を捏造したかもしれないが
かっこいいからとかじゃなくて愚直にOptions APIを使うのはいいぞ。
Comments
うーん、残念だけど全くわからなかった……。
型が綺麗になることって、できることが増えるよりも大事だと思うんですよ。
バグが減るので。
あとscript setupのおかげで、楽にコンポーネントが書けるようになった。
こういうのも大事。
auto importも効くし、Vue3でかなり業務が効率化されてる。
なのでscript setupがデフォルトになってても、おかしくないなあとも思いました。
なんとなく最近思っていたことが全部書いてあった
thanks
わかります。
結局VueとReactという2つの思想があったのに
VueがReact-likeになったことで、Vue派の人は行く宛を無くしてしまった。
うちはもうメインはNuxt3に移動しました、大きく不満のあるものではありません、でも変に複雑になって、シンプルな構造は消えてしまった。VueはVueの強みを失った。それなら別の名前で新たなフレームワークにでもしてれば良かった。
Vue.js3.4?以降に追加される新機能では、Composition APIのみ
サポートされ、Options APIをサポートしない機能がでてきています。
現在、Vue.js の開発チームにて開発中の、Solid.jsにインスパイア
された(テンプレート)コンパイラのSFC用新モード Vapor Mode
(今年の3〜4四半期には続報がある模様) では、Vue.js のAPI の
フルセット ではなく サブセット、<script setup>& Composition API
のみ、サポートされます。
https://blog.vuejs.org/posts/2022-year-in-review
(Vapor Modeでは、CSR用に?vDOMを利用しないDOMベースの
メモリレスでパフォーマンスに優れたコードが出力されます。)
(Vue.js の開発チームの開発リソースは潤沢ではないので、新機能では
Composition API のみサポートになるのは致し方ない面があります。
Vapor Modeでは、パフォーマンス上の理由もあって、Options API
は対象外となっています。)
Vue.js の開発チームは、Composition API を推奨している印象です。
from 公式ドキュメント(Vue.js3)
(個人的には)Options APIは後方互換性のために残されている印象です。
Vue.js3.x では deprecated になることはないですが、4.x以降 では
どうなるかわかりません。(Options API→Composition APIの(利用者の)
移行の進捗度合いにもよります。)
また、Vue.js3ベースのフレームワークである Nuxt3 では、
Compostion API でのみ Nuxt3 独自のAPIや多くのサードパーティ?
製のモジュールのAPIが提供されているので、Options API(のみ) で
開発するのであれば、それら を利用することができません。
Vue.jsまわりのライブラリ群も、今後はComposition APIのみサポート
が増えてくるはずです。
加えて、今年の年末でのVue.js2のEOL(Vue.js開発チームによるメンテ
終了)もあります。
上記を踏まえると、Options APIに留まり続けるのは得策ではないと
思います。
Options API は、(現状の)Vue.jsのコンポーネントの内部表現(データ構造)を
そのまま表出させた感じのAPIで、コンポーネントと密結合していて、柔軟性
に欠けていたので、コンポーネントの内部表現とは疎結合で柔軟性&自由度の
高いComposition APIが導入された、と個人的には考えています。
Composition API→ Options API の変換?が行われているのは、
Vue.js2.7 (2.6以前の2.x + @vue/composition-api) で、
Vue.js3では異なるのではないでしょうか?
それとも、Vue.js3でも、そのようになっていますか?
公式ドキュメント(Vue.js3)には、「Options API は Composition API を
土台にしています!」と書かれています。(なので、Vue.js3で、
Composition API → Options API の変換?が行われている、とは
考えにくいのです。Options APIとComposition APIがチャンポンされている
ケースで最適化etcの理由で行なっている可能性はありますが...。)
案:
Options API でさらさらっと書いて、あとは ChatGPT にお願いして( Composition API にしてもらう)
私もVue2に魅せられた一方で、Vue3は最近まで踏み出せなかった一人です。
仰る通り、当たり前のようにポンと出され混乱してしまい、複雑そうという先入観を拭いきれませんでした。
あと、公式(VueRouter/Vuex)や準公式(Vuetify)ライブラリの足並みが揃わなかった(ように見えた)のも大きいです。
ここ数週間で、流石にそろそろ触っておくか...と重い腰を上げてCompositionAPIを使い始めましたが、やはりと言いますか、後発なだけあっていざ使ってみると凄い便利で、今はもう普通に使ってます。
しかしCompositionAPIが使えるようになった今でも
<script setup>は頂けないと思っており、これは今後も変わらないと思います。ボイラープレート排除という大義名分のなか、ハイコンテキストになり過ぎたのかな、という印象です。
メインはバックエンド(と最近は言い切れなくなってきましたが…)の立ち位置から見ると、
Vue3とComposition APIってめちゃくちゃわかりやすくなったという印象しかなかったかも。
確かに最初ref周りでつまずいた記憶はうっすらありますが、
それ以上に、全体的に定義がシンプルになった印象があります。
個人的に当時Svelteを勉強してた(理由は楽そうだから)というのもあって、
vue3、Svelteまんまやんけ!と思った記憶。
Vue2から移行した自分がうーんって思ってることが纏めてあって救われました。
refとreactive、自分もフガッ!!となりました。
ただ結果として、templateで使うvariableやfunctionの実装をSFCの外に書くようにしているので、全体の見通しは宣言的に書きやすくなったな、という実感はあります。
まずはreactiveとrefの違いから勉強したほうがいいと思う。ググればすぐ出てくるから。
じゃあReactとか他のでいいよね、ってなっちゃうよなあ。。
webエンジニアとしてReact、Vue、Nuxt、Next、Nest、Nodeを使いこなすのが基本要求ではないかと思います。ほぼグーグルで検索したり、コピペしたりするから、正直、大きな違いがない気がします
。
Vue2をVue3に移行したのは二つの大きな潮流があったからです。
1.Vue2のoptions APIは分割代入が使えなかった
時代はECMA6が主流となって、JavaScriptはオブジェクトを分割代入して用いるのが主流になりつつあった時にもVue2はVue.setとVue.deleteという独自のメソッドで処理していましたが、Vue独特の孤立した技術となってしまいました。これらの処理用ライブラリはVue3で廃止になり、options APIで記述してもこれらは使用できません。
2.データ処理の部分でSPAに対応しきれていなかった
JSフレームワークが市民権を得たことで、SPAというルーティングを用いたアプリ開発が主流となっていき、ルーティングにおいて拡張性に優れたReactが大きくシェアを伸ばすことになりました。そこでVue3が導入したのがprovideとinjectという二つのコンテキスト遷移メソッドで、Vue3の最大の長所はこの二つだと思います(Angularも15で追随したほどです)。それまでVue2はイベントバスという非常に不安定で、かつハイリスク(兄弟コンポーネントどころか外部にもアクセスできてしまう)なライブラリを使っていました。また、データ管理はVuexを使用したりしていましたが、これもかなり冗長な動作も多く、データの流れが分かりづらかったので初心者に敬遠されていき、相対的なVue衰微を招いたことがありました。
それからscript setup採用の大きな理由は、無駄に感じたボイラープレートを省略化することと時流に合わせTypeScriptとの親和性を良くするためです(公式サイトにもこの理由を挙げています)。現状の問題点はVue3のscript setupをcompositionAPIと別物だと認識している人が多い(特にVue3から離れた人ほど)ことですね。書いてたらわかりますが、全く同じです(compotionAPIを書いてた人ほどさっと書けるシンタックスシュガー化)。そしてscript setupに慣れたらもはや初期composition APIには戻れないです。
ただ、script setupがCDNに対応していない(海外サイトでもこの手の質問は山程ありました)ので、初心者が学習するならどっちから手を出すべきかは悩むところではありますけど。
setupの記述方法は楽に書けて良い点だと思うんですけど、デバッグツールに定義した変数が無駄に上がってくるのが凄く見辛くて気になってるんですよね。
何か良い方法あるのかな。
CompositionAPIのよくある質問に、Options APIの立ち位置が書かれていました。
ケース・バイ・ケースだそうです。
Vue本体以外使用してはいけない縛りがあるならOptions APIよりも書きやすくなったと思います
だけどライブラリの破壊を上回るメリットではないし、ライブラリが不便なReactのようなものを使用する理由は見いだせません
Vue.js の Composition API の導入を伴う2→3 での破壊的な変更は、
2系の設計時点ではみえていなかった 設計の問題点 / 2系が利用
されること(&2系のメンテナンス)でみえてきた課題 を解決する
ために ライブラリの再設計が行われた結果だと考えています。
Vue.jsの開発チームは、3系で、2系をインクリメンタルに
改善していく方向ではなく、今後を見据え、再設計/再実装を
選択しました。
3系のOptions API は Composition API 上に実装されています。
3系では、2系ではできなかった最適化 etc が可能になり、2系より
性能が向上しています。
3.4でリリースされたComputedプロパティの改良も、2→3での
再設計/再実装 によって可能になった改良です。
Vue.js 3.4 は、2種の代表的な?ベンチマークにおいて、
React 18.2 よりもよい成績となっています。
また、現在、脱仮想DOMによる(更なる)性能向上を目指して開発中の
SFCコンパイラの新モード Vapor Mode は、Composition API
があったればこそ 実装可能となっています。
Let's comment your feelings that are more than good