フロントエンドに触れてみた
作成日時:2022-07-16
更新日時:2022-07-16
1. 概要
- フロントエンドの知識がjQueryの頃から止まっているので、色々触ってみた。
- やったこととか詰まった点を箇条書きで記載していく。
2. Reactを触ってみる
Create React Appというツールチェインで楽にSPA向けの環境構築が出来るらしいのでやってみる。
その他ツールチェインなど:https://ja.reactjs.org/docs/create-a-new-react-app.html
- https://nodejs.org/ja/ からnodejsをダウンロード/インストール。
- 下記コマンド実行(パスが通ってなければ通す)
※コマンドに関してはnpm / yarn / pnpm好きなのに置き換えて。
上記3種に関して→ https://zenn.dev/hibikine/articles/27621a7f95e761
## Create React Appをインストール
npm i create-react-app
## プロジェクト作成 暫く待つ
npx create-react-app (プロジェクト名)
## 開発用にサーバー立ててアプリを起動する。
cd (プロジェクト名)
npm start
- 勝手にブラウザが開いてテンプレートのReactアプリが立ち上がるはず。
不満
create-react-appがなんか遅い。ビルド / HMR / サーバー開始とか諸々遅すぎる。
Reactを勉強する気が失せてしまう。
3. Viteに移行する
Viteというのが上記不満点を色々解決してくれるらしいので導入してみた。
https://ja.vitejs.dev/
## viteをインストール
npm i vite
## create-react-appみたいに環境構築してくれる奴をインストール
npm i create-vite
## プロジェクト作成
npx create-vite
## ↑対話形式で下記の項目を設定
## 1.プロジェクト名
## 2.フレームワーク(vanilla / vue / react / preact / lit / svelte)
## 3.TypeScriptか否かなど
## 開発用にサーバー立ててアプリを起動する。
## エラーが出るなら内容に従って修正
## 多分 @vitejs/plugin-reactが無いとか言われるのでインストールしておく
cd (プロジェクト名)
npm run dev
・ビルド / HMR / サーバー起動、全て爆速である。二度とcreate-react-appは使わん。
・React以外のフレームワークのテンプレも作ってくれるのはありがたい。(SolidJSはまだ無い)
HMR
Hot Module Replacement
ソースを保存したら勝手にブラウザに変更を適用してくれる機能。
今まで変更するたびにF5を押す事しか知らなかったので、最近は便利になったなあと思った。
4. ReactでSPAを作ってみた
爆速開発環境を手に入れたので、何か作ってみた。
最近の不満点↓
・各種技術サイト(Qiita / Zen / etc…)内のブクマとブラウザのブクマがごちゃごちゃになってきた
・上記ブクマを技術内容で検索出来ない。
→なのでReactの練習がてら、これを解消するツールをSPAで作成した。
技術記事管理ツール
- chromeの拡張機能で登録フォームを作成。(1枚目:ボタンを押すと現在開いているページの情報を読み込んで登録フォームを表示する。)
- React SPAで記事の検索 / 情報変更を行う。(2枚目)
感想
- React超便利。学習始めて半日かからず作れた。
- jQuery(命令的UI)に比べたら宣言的UIの方が楽だと感じた。
- ついでにTypeScriptを初めて触った。Java的に記述できて好き
詰まった点とか
- Reactって破壊的変更多い?React-Routerとかググって出てきた情報が、使えないことがあった。
https://zenn.dev/khale/articles/react-router-update-v6 - コンポーネントに記述するkeyは適切な値を設定しないと再描画されなかったりする。(配列のmapでコンポーネントをループで作る時とかkeyが無いと警告出てくる)
https://qiita.com/koba04/items/a4d23245d246c53cd49d - 処理が二重に実行された。strictモードという機能らしく、開発モードのみ起こるらしい。
https://ja.reactjs.org/docs/strict-mode.html - SPAなので当然ルート以外に直アクセスしたりすると404が返ってくる。.htaccessとかでルートを参照するように設定する。
RewriteEngine on
RewriteCond %{REQUEST_URI} ^/foo$
RewriteRule ^ / [L]
5. 自分のサイトを改修してみる
勉強がてら自分の運営しているサイトを最新のフロントエンドっぽく改修してみることにした。
変更前のサイト仕様
- レンタルサーバー
- PHP(フレームワークなし) + MySQL
- 典型的なMPA
- 主なコンテンツはマンガ。DB上に作品情報を格納している。
- サブコンテンツとして技術記事 / ツール / ゲーム等がある。
- サイトのページ数は2,000ほど
- それぞれのページの差分は表示する画像のパスぐらいしかない
- CDNは訳があって使えない。
上記を改修していく
6. SSG
※SSGなどに関しては:https://qiita.com/thesugar/items/47ec3d243d00ddd0b4ed
全ページをhtmlにする。
Hugo / Next.js / GatsbyなどのSSGを使おうと思ったが、面倒くさくなったのでPHPでhtml出力ツールを作成。
全ページhtmlになったので
サイトへのアクセス時にPHPもDBも起動しないのでセキュリティ〇。
SEOや表示速度的も向上したと思われる。
が、似たような内容のhtmlファイルが2,000個もサーバー上に存在することが個人的に気に食わない + ストレージ容量圧迫させたくない。(+ React使いたい)
ので、SSGは止めてReact SPAに改修する。
※仕事だったらSSG / ISR / DSGにする。
7. Reactのファイルサイズ大きすぎだろ
そんなこんなで自分のサイトをReactのSPAで作り直した。
が、Lighthouseのスコアが下がった。
原因はJSのファイルサイズが大きすぎてロードに時間が掛かり、表示が遅くなったため。
確認してみると確かに大きすぎる。(数字は失念)
BUNDLEPHOBIAというサイトでバンドルのサイズをチェック出来るらしいので見てみた。
https://bundlephobia.com/package/react-dom@18.2.0
react-domだけで42KB。jQueryよりデカい。
create-viteを使って他のフレームワークを試してみたがここまでデカくはない。
minifier変えたところでそんなに変わらないだろうし
参考:minifierベンチマーク https://github.com/privatenumber/minification-benchmarks
参考:Viteビルド設定 https://ja.vitejs.dev/config/build-options.html
ejectして外出しにするのもその後が面倒くさそう
参考:https://kisalabo.com/2020/04/16/react-2/
訳があってCDNも使えないしどうすればいい
8. SolidJS
SolidJSに移行した。https://www.solidjs.com/
最終的なファイルサイズも小さくなるしパフォーマンスも向上するし良いことづくめ
ViteにおけるSolidJSのテンプレートの作成方法は公式に記載されている
https://github.com/solidjs/templates
上記で作成したテンプレートのビルド設定等を7で作成したReactのプロジェクトに転記し、ソースをSolidJSの記法に修正した。
ほぼほぼReactとSolidJSの記法は同じなので
・useXXX → createXXX
・className → class
など、文字の一括置換で容易に修正できた。(多少動かなくなった箇所はあったけども)
詰まった点
- まだ日本語記事が少ない。増えてきたけども。
ただ公式サイトが日本語対応〇 + 充実しているので問題はない。 - solid-router(Reactのrouter-dom)で同一パス構造のパスに遷移すると再描画が行われなかった?
例:path=“/comic/:storyId” において /comic/1 → /comic/2に遷移とか
→原因不明(多分signalに対する私の知識不足)。公式と同じ実装にしたら治った。
https://github.com/solidjs/solid-site - 「getOwnPropertyDescriptor」
実行時、コンソールにこれ系のエラーが出て正常に動作しないならばビルドオプションの設定を見直す。
後日、エラーが発生した時と同じ設定でビルドをかけたらエラーが出なかったのでSolid側のバグで修正されたのか?
私の時はビルドオプションのminifierをterserからtrueに変えたら治った。
ReactとSolidJSの違いは?
知らん。下記参照
9. DBデータを全部SPAに突っ込む(愚行1)
SolidJSへの移行が完了し、Lighthouseのスコアも上がった。
が、更なる速度向上をしてみたくなった。
現在のページ表示の流れを見てみる。(SPA)
- クライアント:サーバーに情報要求
- サーバー:DBから表示する表示情報取得
- サーバー:クライアントにJSONで表示情報返却
- クライアント:表示情報を画面に反映
これもうDBのデータを全部JSONにしてSPAに埋め込めば1~3の処理が消えるから速くなるよね。PHPもDBも不要になるからセキュリティ的にも〇のはず。
やってみた→Lighthouseのスコアが下がった。
ファイルサイズが爆増するから当たり前である。
なので下記の対応をした。
- 技術記事など文字数が多いぺージは情報をJSON形式に変換し、ファイルとしてサーバーに配置(一種のSSG的な感じ)
SPAで対象ページを表示する際はajaxで取得してくる。
もちろんPHPは動作しない。 - マンガの情報は表示するページ数程度しか持っていないのでそのままSPAに埋め込む
結果
Lighthouse満点達成
開発者ツールでスロットリングを低速3Gにしてもサクサク閲覧できるようになった。
DBもPHPも使用しなくなったのでセキュリティ〇。
速度も向上。
10. Rust_WebAssembly (愚行2)
もっとファイルサイズを小さくできないか?
→独自のバイナリフォーマットを作れば小さくできるのでは?
データ内におけるマンガの表示ページ数情報を例に考えてみる。
// JSONだと12Byte(= 96bit)
"page":"30",
// 独自バイナリフォーマットにする
// 冗長なので 1Byteを 1話分のページ数とする
00011110
// まだ冗長なのでページ情報を5bitで表現させる(31を超えることはないため)
11110
5 bit / 96 bit = 5.2%
さらにgzip圧縮もあるのでかなり小さくなった。
ちょうどWebAssembly(wasm) に興味を持っていたし、バイナリ読み込み処理をwasmで実装する。
WebAssembly
https://developer.mozilla.org/ja/docs/WebAssembly
上記サイト引用
WebAssemblyはウェブプラットフォームに大きな影響を与えます — 以前ではできなかったようなウェブ上で動作するクライアントアプリケーションのために、複数の言語で記述されたコードをウェブ上でネイティブに近いスピードで実行する方法を提供します。
大雑把に言うとブラウザ上でバイナリコード動かして爆速にする。
色々と使われている。
- Google Earth
- ブラウザ上で動くファミコンのエミュ
- Pythonをブラウザで動かす(PyScript):https://pyscript.net/
- クラウドネイティブ
- Unity WebGL
- Flutter for WebのHTMLレンダラ
- etc…
下記サイトを参考に実装してみた。(言語はRustを使用)
https://dev.classmethod.jp/articles/rust-webassembly-javascript/
wasmへのバイナリデータ埋め込みは自作したRust用のxxd -iコマンドみたいなツールを利用して埋め込む。
ビルドを行うとTypeScript用の型定義ファイルが出てくるので、TypeScript使ってるならそれを読み込む。
ビルドサイズが大きい場合は最適化オプションを設定する。
https://zenn.dev/dozo/articles/14b76b561f3b45
結果、ファイルサイズの縮小と若干の速度向上は出来たけれども、
下記の点が問題なのでおとなしくJSON埋め込みverに戻した。
愚行だった点
- 実装が何もなくてもwasmを使うためのライブラリで15KBくらい必要になる。
→下手すればファイルサイズを減らす取り組みで逆に増える。 - 保守性が著しく悪い
- バイナリフォーマット解析するだけならwasm不要だしJSで解析すればいいじゃん。
→今回の実装を全否定
まだ試してないけどもZig使ってwasm書いたらどうなるんだろう。変わらんか
https://ziglang.org/ja/
※念のため記載するが、wasm上に見られたら困るようなデータを埋め込むな。JSと同じで基本全部参照可能
https://i-407.com/blog/m7/
11. まとめ
雑多に記載していったので特にまとめとかは無い。
各技術における個人的な感想とか考えを記載していく。
SolidJS
- パフォーマンスの良さとファイルサイズが小さい点でReactより好き
- 早くISR / DSGツールが出てくればいいな
wasm
- 正直、自分がアサインされるような案件では使うことは無いだろうなと思う。間接的には使うかもしれないけど(ゲーム系とかツール系案件なら直で使ったりするか?)
ただRustの勉強がてら、プライベートでは若干いじる。 - (参考) WebAssemblyの利用シナリオを調べる
https://zenn.dev/takewell/articles/11b80090137dcc
Rust
最近勉強しようかなと思っている言語
- wasm書ける
- 低レイヤ書ける
- Tauriでクロスプラットフォームなデスクトップアプリを作れる
- メモリ安全、スレッド安全
- C / C++ と余り変わらない速度
と、色々良さげっぽい
以上
(おまけ) 個人的に体感したwasmによるパフォーマンス向上事例
この間、OpenCV (https://opencv.org/) + Pythonで画像解析をするWEBアプリを作成したがサーバーが貧弱な為、異常に処理が遅い。
そこでOpenCV.js (wasmで動くOpenCV) を使ってクライアントで画像解析処理を行わせることにした。
OpenCV.js:https://docs.opencv.org/4.x/d5/d10/tutorial_js_root.html
結果として爆速で動くようになった。
それも当たり前で、画像のアップロード / ダウンロードの時間も消えて画像解析は貧弱サーバーではなくクライアントで行うのだから。
旧:画像アップロード(遅) → 画像解析(遅。複数リクエストが来たら死) → 解析/変換した画像返却(遅)
新:クライアント内で完結
重い処理をクライアントでやらせればサーバー負荷(またはLambda起動)が掛からんし、クラウド料金とかを安くできそう。
ただwasmファイル自体が重いので初回ロードに時間が掛かるのデメリットか。
(CDNとか使えばまあ若干改善できるし、2回目以降はキャッシュ使うから大した問題ではないか)