Open12
2021年現在Vueを選択すべきでないと思う理由 感想
Vueに対する熱いメッセージを頂いたので感想を述べてみる(ここが解決されればVueを率先して使ってくれるという意味と受け取った)
コンポーネントのローカルスコープでコンポーネントを定義しようとするとJSXが必要
- わかる
- 主にTailwindCSSのようなユーティリティファーストとの相性の悪さ
- スタイリングはテンプレートレベルで分岐すべき場合が往々にしてある
- Vueは動的クラスが主流なため、ユーティリティクラスを付け替える場合computedで文字列を返すとかstyleブロックでapplyすることになりがち
- 本当に課題になってきたらVue自身が対応するとは思う
JSXが嫌でReactを使わないならSvelteがあり、SvelteはゼロオーバーヘッドでVueより速い
- コンポーネントが作られたり消されたりするような場合一定の閾値でVueの方がバンドルサイズが軽くなる
- [Draft]VueとSvelteのサイズを比較検証した「vue-svelte-size-analysis」を掘っていく
- とはいえエッジケース
- 〇〇倍速いみたいなやつ、知覚したことない(フレームワークパフォーマンスを気にする前にやるべきことが沢山ある)
- ほぼラインタイムを消し去りたい、20kb未満のアプリケーションを作る必要があるとかだとSvelteは強そう
- https://zenn.dev/mizchi/articles/8a017097d3994ddc0a85
- Next、NuxtのようなSSR/SSG用途で十分に使われてるようなフレームワークがまだない
- SvelteKit(SvelteNext)はあるが、採用事例が国内であんまりない(なさそう)
- https://uit-inside.linecorp.com/episode/80 で拾える状態からどの程度成熟しているかが論点
- 2021年今すぐに採用したいかと言われると微妙な気がする(挑戦はしてみたい)
- そもそも論、React、Vue、Svelteを直で使うことよりNext、Nuxt、SvelteKitの選択になるよね
React+JSXと違って、マークアップをJavaScriptのデータ構造として扱えない上、TypeScriptとの相性も悪い
- 単に相性が悪いと言っても何がどこまで出来ないのか語られてることが少ない
- React(Next)+ tsx と比較してということであればわかる
- これに関してはもう少し何ができたら良いのか(Vue + tsxでできないことはなにか)を明確にしてほしい
- 自分は難しいとは思いつつ型が効かないなぁと思ったことはない(Reactのようにはならないのはそれはそう)
- 手段がないのか、知られてないのかではやるべきことが違ってくるので
Slotに渡す引数の型が指定できない(TypeScript)
- 考えたことなかった
- Slotをrender functionと捉えるとその引数の型(レンダリングするコンポーネントの型)を指定したいのはわかる
- 現状v-slotにコンポーネントの型をつける方法はないかも(知らないだけかも)
- できると便利そう
ジェネリックなコンポーネントが作れない(TypeScript)
- 直接の解決ではないが動的コンポーネントというのがある
- https://v3.ja.vuejs.org/api/built-in-components.html#component
- props で要素の文字列をもらってレンダリングする要素を変える手法がよく使われる(特定条件でリンクをdivにしたい等)
Propsに関数を指定したいときもあるのに、イベントをemitするパターンが推奨されている為、仕事場で他メンバーの目が気になる
- Vueを選ばない理由に並べるのは乱暴な気がする
- どちらも使い道があり、使う理由がある
- props functionは親が子の振る舞いを決定する時に用いる
- emit は子の振る舞いに親が関心を持たず、イベントの通知(とペイロード)を受け取りたい時に用いる
- 思想、設計方針の違いで使い分けると良い
- 「プロジェクト内で統一されてないと気持ち悪い」という言説は気持ち悪くない人もいるので真に受けなくて良い
- 文句があるなら俺の設計を超えてみろという気持ちが大事(口に出す時はマイルドにしよう)
emitされるイベントの型が効かない(TypeScript)
- Vue3ならVolar(Vue Language Features)によるサポートがあります(Veturだと無理)
- https://github.com/johnsoncodehk/volar
- emits プロパティに記述したvalidator関数((payload) => validate)の引数型が親に伝わる
- 型が合わない値を親で受け取ろうとするとエラーになる
- v-modelを使うと推論されない(2021/09現在)
- なんかドキュメントになかった気がするので知らない人の方が多そう
- tsのサンプルが公式に少なすぎるのが問題か
Vue2からVue3へのBreaking Changeが、Deprecatedで十分そうなものが廃止になっていたりするせいで、移行はかなりきつい
- やればできる、やらないからできてないだけ
- 移行用ビルドがある
- マイグレーション方法も明示されている
- https://v3.ja.vuejs.org/guide/migration/migration-build.html
- Vue3向けのESLintを使うことで非推奨になった機能をLintで落とすことができる
- https://qiita.com/ota-meshi/items/ff0d70ef326657249727
- ReactのClass Componentからhooksに移行したみなさんなら余裕だと思う
- 別にcomposition apiに書き直す必要はない
- Nuxtに関しては3で2との互換性を維持しつつ動かせるようにしているらしい(Nuxt Bridge)
- 試せる人はお手元のNuxt2プロジェクトに以下をインストールして使ってみよう
- https://www.npmjs.com/package/@nuxt/bridge-edge
package.json
"devDependencies": {
+ "@nuxt/bridge": "npm:@nuxt/bridge-edge@0.0.0-27194113.64a4265",
}
yarn install
nuxt.config.js
buildModules: [
+ '@nuxt/bridge'
],
+ bridge: {
+ nitro: true,
+ // vite: true
+ },
で開発サーバーを起動するとNuxt Bridgeの互換モードで起動する(tailwindcss moduleを使っている場合外さないと動かない)。
Provide/Injectで、状態に応じてProvideしたりしなかったりができないので、undefinedとの闘いから抜け出せない
コンテキストの機能を提供するProvide/Injectで型が効かない(TypeScript)
- 同じ関心事なのでまとめます
- もう少し詳しく説明すると、injectするコンポーネントがマウントされるタイミングでツリーの親を全て探索してprovideされているキーを発見する仕組みなので、存在しなければundefinedが返る、という話
- 「状況に応じてprovideしたりしなかったり」はprovideだけするコンポーネントをコンテキストとして用意してマウントし分けるとか?
- inject側は同じフラグを参照してinjectするか決めるか、undefinedのハンドリングが必要
- それはそうな話な気がする、自分が理解しきれてないだけかも
- InjectionKeyを用いるとprovideする値、injectする値の型を指定できる
- https://zenn.dev/ushironoko/articles/e5b86383f3eb3098bf7f で前に書いた
Vuexはdispatchする時、型がまともに効かない(TypeScript)
- Vuex5でまともになる
- どんな感じかは前にVuejs Amsterdamで話されてた
- https://youtu.be/WmgQH4pOhUc (英語)
- ただ、もはやFluxではなくコンポネライフサイクル外で生存するグローバルストアにaction→state→getterのサイクルがあるだけというものになった
- Vuex4で型を頑張りたい場合、https://github.com/ktsn/vuex-type-helper がおすすめ
- ヘルパーだけで型をマシにできる
- this.$storeの方はダメ
- https://zenn.dev/ryo_kawamata/articles/intoroduce-vuex4-with-composition-api が詳しい
vuexの型は、僕はtyped-vuexがおすすめ