🧊

Preactを使いたいのに使えない

という気持ちが高まったので、とりえあず2020年末の情報として、書き残しておくことにした。

Preactとは

preactjs.com

いわゆるReactのジェネリックで、`react-dom`が圧縮しないと130KBくらいあるところ、なんと3KB!というもの。

Reactとの互換レイヤーである`preact/compat`を使っても、余裕でお釣りがくるというわけで、ぜひとも使いたい!となる。

なんでそんなに軽いのかも書いておくと、

  • `react-dom`がやってるイベントシステムを実装してない
    • DOMネイティブのを使ってる
  • コードゴルフがんばってる
    • 読めばわかるけど、結構がんばってる
  • VDOMの実装も最低限

というわけで、軽量さにフォーカスして書かれており好感が持てる。

基本的にはよい

Hooksも使えるし、基本的にはなんの問題もなく、そのうえ軽くてよい。

`className`って書かなくていいとか、`onChange`が本来のDOMの`onchange`と挙動が違うとか、なんでやねんReactみたいなところも解消されてる。

ちょっと規模が大きくなっても、全てのライブラリを自分で書く場合とか、Viewまわりに関して特に依存がない作りになってるなら問題ない。
このラインの内側にいる間は、なんの憂いもなくReactを捨てられる。

ちなみに`preact/compat`だと、`Suspense`と`lazy`みたいなモッダーンなAPIまで生えてたりする。

TypeScriptとエコシステム

Preactは型定義もちゃんと提供されていて(たまにちょっとおかしいけど)、TypeScriptでも普通に使える。

なので、上述のような規模のものをTSで書く場合も、なんの問題も起きない。

ただし、Viewまわり(つまりReact)に依存したライブラリを使いたくなったときに、地獄がはじまるのである・・。

`preact/compat`は、ReactとPreact感のJSとしてのAPIの互換性はあるものの、型定義はまったくの別もの。

なので、いわゆる「Reactを前提として書かれたライブラリ」のほとんどが、「ReactのXXXっていう型がない!」っていってコンパイルできなくなる。

そしてこの対応がほんとうにだるい・・。
Preactにしようと思ったけど、やっぱReactに戻すわ・・っていう意思決定をするくらいにはだるい。

`goober`みたいにReactでもPreactでも使えるように設計されてるものは本当に稀で、`react-`を冠するライブラリは基本的にそのまま使えないと思っていいと思う。

ありとあらゆるReactの型をPreactのそれにエイリアスする独自の型ファイルを用意するしか道がない。

もしくは、その使いたいライブラリのPreact向けを自分で書く。

ただ、MobXのPreactのバインディングを書いてみた(そしてメンテするのを諦めた)身として、あまりおすすめしないかも・・とだけ書き残しておく。
PreactとReactの内部構造は違うので、React都合に寄ったコードを見たとき、どう扱っていいのか判断に困るから。(だいたい無駄かもしれないと思いながらも、そのままコピーしてしまう)

TypeScriptにしたい気持ちが高まってくる規模感のものを、型の問題の対処が面倒すぎるからJavaScriptで!っていう択を選べる人類は、そんなにいないのではないかなーと。

Preactのこの先

Reactの場合、Concurrent Mode(以下CM)ってのが実装される予定・・というロードマップがあるけど、Preactには来るのか?とか。

Preactの現メジャーバージョンは10で、11を出すにあたってどうする?っていうIssueにその答えがある!

The road to Preact 11 · Issue #2621 · preactjs/preact · GitHub

CM自体、既存のライブラリとの互換性の問題とかもあるし、そもそも本当に必要なのかまだはっきりしてない・・とのこと。

まあCMなんか実装しようものなら、サイズ爆増待ったなしでは?っていう気もするし、Preactには来ないのでは?という気がしてる。
あと冒頭でFast 3KB Alternativeって言ってるけど、地味にサイズは増えてきており、実はもう4KBくらいあるんやけど。

ただ実際のところ、Preactを使ってReactから125KBばかりのダイエットに成功したとしても、他のライブラリが軽くそれを取り返してきたりするし、いろいろと悩ましいな〜と思う今日このごろ。
本気でサイズを減らしたいなら、Svelteでいいのでは?ってなるし。