webフロントの流行りを調べてみた(Vite, tailwindcss, swrv)

WRITER: admin
2021/12/20

本記事では、触ってみた、やってみた系ではないので、コードの書き方に関しては記述しません。
どういった技術なのか簡単に知りたい方向けです。

Vite

一年前くらいから流行っているViteに関して調べた

Viteとは

Vue.jsのビルドツールといえば、vue-cliでした。これに変わる可能性が高い存在としてViteが現れました。
Viteとは、Vue.jsの作者のEvan You氏が開発中のノーバンドルなビルドツールです。
大きなメリットとしては以下の2点になります

  • 開発時はバンドル不要で動作するので、大規模プロジェクトでも初回起動が非常に早い
  • HMR(画面の再描画無しにファイル変更をブラウザに適用してくれる機能)が、モジュールの総数と切り離されているため一貫して高速に動作する

字面でなんとなく開発が速くなるのは理解できると思います。
そのほかの特徴としては、

  • viteは、Vue.js限定ではなく、React、Preactにも対応
  • Rollup.jsをベースとしたプロダクションビルド機能
  • 開発ビルドは、 esbuildを使っている。Goでかかている為JavaScriptベースのバンドラーよりも10-100倍速い。

さて、バンドル不要とはどういうことでしょうか?、モジュールの総数と切り離されているとはどういうことでしょうか?
この2点を理解するのに必要になるのがNative ESM(ES Module)です。

Native ESMとは

本記事ではあまり深く解説しません。詳しく理解したい方はNative ESM時代とはなにかの記事がわかりやすくまとめられており、これからどうなっていくのかもわかり、とても勉強になります。

Native ESMとは、ES Modulesのことです。2015年にECMAScriptの標準仕様になり、モダンなフロントエンド開発において広く用いられている、import宣言でインポートしexport宣言でエクスポートするのがES Modulesです。
vue-cliでは、ビルド時にバンドラによってimport・exportで繋がった複数のJavaScriptファイルたちを一つのJavaScriptにまとめる処理が行われます。つまり、ビルド前にES Modulesを利用していたとしても、ビルド後のJavaScriptではもはやES Modulesが使われいないことになります。
この一つにまとめるという処理(バンドル)は、単純に全てのファイルを繋げるだけではなく、辻褄を合わせるためにランタイムのコードを生成したりしています。この作業は、プロジェクトが大きくなればなるほど時間がかかるものになります。
このバンドルは、開発環境においても同様に行われておりファイルを編集するたびに裏で動いているため、開発環境を快適にする、効率をあげるという意味でもバンドルの高速化が重要になっていきます。
バンドルのフローは以下の図のようになっています。

引用: https://vitejs.dev/guide/why.html#slow-server-start

そこで登場するのがNative ESMです。ビルド後の成果物にもES Modulesの利用が含まれる(言い換えれば、ビルド後の成果物が複数ファイル(モジュール)から成る)ようにしようというのがNative ESMです。
現在のNative ESMの開発環境では、そもそもバンドルせずにブラウザにESMを読み込ませる(複数ファイルを読み込ませる)。これによりビルドにかかる時間がなくなり、開発の効率が上がることになります。
Native ESMでのフローは以下の図のようになっています。
引用: https://vitejs.dev/guide/why.html#slow-server-start

HMR

さらに、HMRを行う際も、部分バンドルの作成のような面倒な処理をする必要が無く効率的です。
HMRを有効にするには、HMR境界を定義する必要があります。HMR境界とは(viteだけの用語?)、「このモジュール(およびその依存モジュール)が書き換えられたときはこのモジュールだけ再読み込みすればよくて、このモジュールに依存するファイルたちは再読み込みをする必要がない」という宣言です。HMR境界があれば、その内側のモジュールが更新されたときは境界の内側のみ再読み込みし、外側はそのままということが可能になり、効率がよくなります。これを設定するのは、かなり労力が必要になるが、Viteの場合、Reactプロジェクトに対しては@vite/plugin-react-refreshがこの設定をしてくれます。これにより、ReactコンポーネントのみをエクスポートするモジュールがHMR境界となり、ビルド・再読み込みのパフォーマンスが最適化されます。
これにより、モジュールの総数と切り離されているため、HMRが高速化されるということになります。
これらによりViteでは、開発時のビルドの高速化に繋がります。

その他参考資料

Viteを使ったvueプロジェクトの作成に関して

【Vite】 Vue3.0もReactも!ノーバンドルなビルドツール「Vite」を試してみる

どれくらい速くなったのか検証
Vite は本当に早いのか ~ Vue CLI と比較 ~

Vite公式ページ

 

tailwindcss

次は半年前くらいから話題になっているtailwindcssです。
tailwindcssに関しては、個人的に懐疑派でとりあえずプロジェクトで1回使ってみたいなって感じです。

tailwindcssとは

ユーティリティクラスが大量に詰め込まれたライブラリーがcssです。
ユーティリティクラスとは、Bootstrapでよくあるmt-3とかがそれにあたります。
tailwindcssに関しては、新しい技術というよりは、css設計に関する話になっています

なぜ今更ユーティリティクラスなのか

cssは長い歴史があり、現在の主流のcss設計はBEMです。
BEMが主流となったのは、

  • cssがプロジェクト全体で共有されてしまうため、命名によって意図していない箇所に適用されないようにするため
  • 単純なHTMLとCSSだけのプロジェクトだと、構造がわかりずらいので命名で分かりやすくするため

という2点が大きいです(多分)。
プロジェクトが大きくなるとclassの命名には5分くらい掛けることもあり、コードを描いてる時間より名前を考えてる時間の方が長くなったりしていました。
しかし、Vue.jsとReactなどのコンポーネント思想によりこの2点の影響が少なくなってきました。
コードの全体像に関しては、小分けにされているため構造がわかりやすくなり、cssに関してもコンポーネント内でしか影響を与えないようになりました。
これにより、命名に頑張らなくても良くなり、ユーティリティクラスが導入できるようになりました。

cssをまとめる

tailwindcssには、@applyを使うことによってcssをまとめることができます。書き方に関しては、調べればたくさん出てくるのでそちらを参考にしてください。
bootstrapなどには、btnなどのclassが存在していますが、tailwindcssには存在しません。そのため、毎回classに大量のクラス名を記述するのは大変になります。これを解決するのが@applyになります。これにより、頻度の高い構造体に関しては、まとめられ可読性も向上し、再利用性も高くなります。

繰り広げられる討論

さて、設計の話になってくると通常宗教戦争が勃発するように、tailwindcssについても賛否両論となってます。
tailwindcssは、確かに命名に掛ける時間が短縮されてコードに専念できるようになった一方、classが多くついてしまう、初期の学習時間がかかるなどの声が多くあります。また、かなり凝ったUIを実現しようとすると実装しにくいなどのデメリットもあるらしいです。

個人的な意見

既存のプロジェクトにbootstrapが入っていない、素のcssを使っているのであれば導入してもいいのかなといった感じです。また、bootstrapを導入しているが、足りずに自分でもcssを書いたりすることが多いプロジェクトに関しても導入を検討してみるのもいいではと考えてます。

その他参考資料

なぜ Tailwindcssなのか? CSSのパラダイムを振り返ってみた
TailwindCSSって何?なんで流行ってるの?
それでも私がTailwind CSSではなく、CSS Modulesを推す理由
ユーティリティーファーストとTailwind CSSのススメ

swrv

swrvは、SWRというデータ取得時の非同期処理の管理とキャッシュ管理を行うための、React Hooks向けライブラリを、vue hooks向けライブラリにしたものです。

swr(stale-while-revalidate )とは

stale-while-revalidateは、RFC5861で策定された効率的なHTTPCache-Controlを実現するための戦略で、2つのキャッシュ戦略が示されています。

  • stale-while-revalidate
    • 指定された期間に行われるキャッシュの再検証中は古いキャッシュを返す
  • stale-if-error
    • 指定された期間にネットワークエラーがあった場合古いキャッシュを返す

指定された期間は、キャッシュの生存期間とは別に指定します。例えば max-age=600、stale-while-revalidate=600 とすると20分間保持したキャッシュを返却します。ただし、stale-while-revalidate が有効なのは再検証が終わっていない間で、キャッシュが破棄された場合は次のフェッチでサーバーへ問い合わせを行います。
RFC2616では、「慎重に検討された状況」では期限の切れたキャッシュを返却しても良い、ということになっています。古いキャッシュというのはキャッシュの生存期間を過ぎてもstale-while-revalidate、または stale-if-error の値に基づいて返しても良いキャッシュ、つまり「慎重に検討された状況」で返しても良いキャッシュのことを指します。

簡単に言い換えると、まずは既存のキャッシュを返して(stale)、そのすぐ後にバックグラウンドで通信を行って、既存のキャッシュと取得したデータに違いがないかを検証します(revalidate)。キャッシュを更新している間に古いキャッシュを返すことで、ユーザーに遅延を感じさせないようにキャッシュコントロールできます。
SWRはこの2つをうまく落とし込んだライブラリです。stale-while-revalidateを自動で行い、さらにユーザコードから非同期処理を隠蔽することで stale-if-errorを楽に実装できます。そのため、React界隈では頻繁に利用されているライブラリーとなっている。

swrvのその他機能

重複削除機能

同じページ内で、同じAPIが2回以上呼ばれている時、1つになるように調整してくれる機能がある。
例えば、ダッシュボードページにheaderコンポーネント、ユーザ情報コンポーネントの2つのコンポーネントがあり、両方でuser/:idを叩いていた場合、片方だけが呼ばれるようになります。(めっちゃ便利)

インターバルポーリング

データが更新されているかどうかを確認するとき、すべてキャッシュからサービスを提供。また、ユーザーがオフラインまたはウィンドウがアクティブでない場合はポーリングを停止する。

その他参考資料

swrv公式
Data Fetching using Vue Hooks
Vue に stale-while-revalidate がやってくる
そうです。わたしがReactをシンプルにするSWRです。