こんばんは。
この記事でSvelteに触れた後、Vueをフロントエンドに採用してTauri開発を続けていたのですが、またしても壁に突き当たってしまいました。
VueはJavascript内でツリーを構築して仮想DOM
を操作して画面描画を行う技術です。
知ってる人も多いと思いますがこの仮想DOM、差分検出や更新処理を行うのに負荷が重くなりやすいのが欠点です。
SSRのWEBアプリなら多少の融通は聞くかもしれませんが、Tauriではあまりにも重い処理が続くとフリーズを起こします。
仕事でサーバーのステータスチェックアプリを設計していたのですが、疎通確認のボーリング処理を行うコンポーネントを複数置いたところ、アプリ自体が起動後即フリーズするという事態に陥り、泣く泣くSvelte版での開発に戻しました。
このままVueを使い続けるのもしんどそうだなと思い、
- 仮想DOM不使用
- SSRじゃない
- 書きやすく軽い
という3点に絞って代替技術を探していたところ、ついに運命の相手に巡り合えました。SolidJSです。
SolidJSって?
SolidJSは個人開発者のRyan Carniatoさんによって開発されたWebフレームワークです。
ReactやVueやSvelteと同じくコンポーネントやリアクティブなDOM描画の出来る機能を備えており、
2022年のState of JavascriptではSvelteを抑えて興味のあるフレームワーク第一位に輝いています。
基本的にはReactと同じjsx/tsxを使用した構成ですが、Reactと違い仮想DOMを使用せず、高いパフォーマンスを誇っています。
こちらのサイトによると、なんとSvelteを抑えてVanilla Javascriptに次ぐパフォーマンスを実現したのだとか
また、SolidJSではReactで状態管理に使用されていたReact Hookの代わりに``Signal``という技術を採用しています。
Reactにほとんど触れずに生きてきたので詳しくは分かりませんが、Signalは仮想DOMに触れず直接値を更新するためパフォーマンス・安定性ともに優れているのだそう。
実際にSolidで前述のサーバー管理アプリの再構築を行い、Signalで状態管理を行うよう実装してみましたが、Svelte同様に軽快に動作してくれました。
ReactでいうところのNext.jsにあたるSolidStartも先日Version1.0に達したそうなので今後が楽しみです。
褒めポイントその1、JSXって良いよね
今回初めて本腰を入れてjsx/tsxの記法を学んでみましたが、Webフレームワークのお作法に慣れているとVueやSvelteのテンプレートより全然書きやすいです。
むしろreturnでHTMLを返すというJavascriptルール主体の構造な分パッと見て把握しやすい。
WEBフレームワークを紹介するサイトでよく
「Reactはjsxが難しく学習コストが高いからVueのほうがいいよ」
的な案内がされていますが、第一印象で面食らうだけで書き始めてしまえば他のフレームワークよりよっぽど頭に入りやすいと思う。
import { createSignal } from "solid-js";
import "./App.css";
const App = () => { //関数を宣言
const [message, setMessage] = createSignal(""); //必要な処理を実行
setMessage("にゃんこ大戦争")
return (//returnでHTMLを返す
<main class="container">
<h1>{ message() }</h1>
</main>
);
}
export default App;
上から下に流れて最後はHTML要素をreturnするというシンプルな構造です。美しい……
褒めポイントその2、Signalが便利
Solidで標準実装されているSignalが滅茶苦茶使いやすいです。
SvelteのRuneと同じで、コンポーネント外でも宣言可能で、importすることで複数コンポーネント間でリアクティブな値を共有できます。
下図の例では、コンポーネントAでSignalに値を代入すると、もう片方のコンポーネントBでも値が更新されてにゃんこ大戦争が表示されます。
import { createSignal } from "solid-js";
export const [message, setMessage] = createSignal("") //作成したSignalとsetterをエクスポート
import { message, setMessage } from "./signal";
const A = () => {
setMessage("にゃんこ大戦争")//シグナルに値を代入
return (
<main class="container">
<h1>{ message() }</h1>
</main>
);
}
export default A;
import { message } from "./signal";
const B = () => {
return (
<main class="container">
<h1>{ message() }</h1>
</main>
);
}
export default B;
アプリ開発でも、設定値などをいちいちファイルから読み込むより共有のState等に格納していつでも引き出せるようにしておいたほうが効率が良いため、コンポーネントを超えてグローバルな値を簡単に持てるのは嬉しい。
VueにもPiniaがありますが、refを宣言するのと同じぐらいの手軽さで実装できる分Signalに軍配が上がります。
褒めポイントその3、デベロッパーツールがある!!!
言わずもがな。
そもそもSvelteを諦めた最大の原因が最新版で動くdevtoolの欠如だったので、コンポーネント間の状態をリアルタイムで追えるdevtoolの存在は決定打です。
ブラウザ拡張機能のみならずTauri環境でも実行可能なoverlayバージョンもあるなど多方面に手厚いのも100点満点
おわり
SolidJSもSvelteに負けず劣らず将来性のあるフレームワークなので、Tauriでの採用を足掛かりに学習も兼ねて触れてみると良いと思います。
SolidJS→Reactっていう学習の派生も全然アリだと思う。