Chapter 06無料公開

Isomorphic JavaScript

okmttdhr
okmttdhr
2021.01.14に更新

Isomorphic JavaScript(Universal JavaScript)は、クライアントとサーバーの両方で動くJavaScript、あるいはJavaScriptアプリケーションのことを指します。

いくつかのユースケースや技術を紹介してゆきます。

Server Side Rendering

典型的な例として、ReactアプリケーションのServer Side Rendering(SSR)があげられます。ReactDOMServerなどを使用してサーバーサイドでMarkupを生成し、動的なビューもサーバーサイドから返す仕組みです。

これによって、Client Side Renderingで発生していたパフォーマンス面のボトルネックや、SEO最適化やOGPの問題を解決します。また、「テンプレート」にReactなどのVirtual DOMライブラリを使用することができ、従来の、テンプレートエンジンによる非効率なクライアントサイドプログラミングを避けることができます。

この文脈でのSSRには、Rehydrationという技術があります。サーバーから返されたMarkupに対して、クライアントのランタイムで動的な機能を追加するというものです。Rehydrationができるということは、例えば、Client Side Renderingも可能です。初期描画のみSSRされたアプリケーションを表示、その後、クライアント側でRehydration、以降はClient Side Renderingを行うという仕組みで、こちらは一般的なサーバーサイドアプリケーションに対して優位な点と言えるでしょう。

BFF

BFF、あるいはAPI GatewayレイヤーとしてのNode.jsも、SSRとしてのIsomorphic JavaScriptの拡張と捉えることができると考えます。基本的に、CPU highな処理はバックエンドにまかせてAPIで通信することを想定しています。Node.jsのORMは他の言語のものに比べて個人的に好きではありませんが[1]、BFFレイヤーとしてであればうまくフィットするというのが私の考えです[2]

Microservice Architectureのチャプターでも少し触れましたが、Gatewayレイヤーがシンプルであり続けるためには工夫が必要です。Node.jsのAsynchronous & Non-blocking I/Oを実装しやすい性質、TypeScriptによる強力な型サポートは、このレイヤーで動く言語としては悪くないと考えます。

Next.js

SSRには技術的な煩雑さがありました。例えば、サーバー側でのみ動かしたいデータ取得の処理、Reduxなどのステート管理のレイヤーにデータをRehydrationする処理などです。

それらの面倒ごとをカバーする技術として登場したのが、Next.jsやNuxt.jsなどのフレームワークです。それらはSSRのためだけのものではありませんでしたが、SSRの難しさをラップしてくれるというだけで当時はインパクトがありました。

加えて、API routeという仕組みでバックエンドの実装ができるので、BFFや、JAMstackのチャプターで触れたSSGのためのエンドポイントなどの用途が期待できます。ユニバーサルなバンドリングをほぼゼロコンフィグで使える点も魅力的です。

また、Isomorphic JavaScriptからは少しずれますが、SSRやSSG、Incremental Static Regenerationをハイブリッドで構築できるのもユニークな点です。より詳しくは https://nextjs.org をご覧ください。

メリット・デメリット

メリット

Gatewayレイヤーをひとつの言語で開発し、アプリケーションの「フロント」をJavaScriptだけで面倒を見ることができるのは、スイッチングコストの削減に繋がり、分散システムのチーム開発においては効果を発揮すると考えます。また、前述したAsynchronous & Non-blocking I/Oな性質で大量のリクエストをさばくことが得意です。

Webからずれてしまいますが、比較的デバイスを問わずどこでも動作するという点で、プログラムとしてのポータビリティが高いことも挙げられます。クライアントをJavaScriptで実装し、セットで使えることが多いです。

デメリット

Isomorphic JavaScriptそれ自体のデメリットというよりは、Node.jsやJavaScriptの弱い部分を理解しておく必要があります。例えば、大きいものだと、前述したCPU highな処理に不向きな特徴が挙げられます。

JavaScriptという言語としては、ビルドプロセス、エコシステムの複雑さがあると私は感じます。昨今のJS界隈では、TypeScriptやテストなどを考えるとビルドが前提となっており、周辺のエコシステムやコンパイラの仕様などを理解して使うことを考えると、他の言語と比べると比較的複雑な世界となっています。TypeScriptはたしかに素晴らしいのですが、そのあたりの複雑さは畑が異なると難しさを感じると思います。

また、言語として自由すぎる点はメリットにもデメリットにもなります。マルチパラダイムでいろいろな書き方ができてしまうので、非同期処理の実装や、パッケージストラクチャなど、技術者によっては辛いと感じてしまうこともあるでしょう。

まとめ

Isomorphic JavaScriptは、SSRを始めとし、アプリケーションのフロントエンドをまるっと提供できる選択肢を提供します。ユースケースにあった使い方をすることで、他の言語にも引けを取らないメリットがあることがわかりました。

脚注
  1. 筆者はSequelizeとTypeORMしか使ったことはありません。 ↩︎

  2. 逃げとしてのNoSQLも好きではないです。 ↩︎