Web Application Architecture#

Webアプリの設計パラダイム

Multi-Page App (MPA)#

ユーザーのリクエストを受けて、サーバー側でレンダリングしたHTMLを返す。

UIの更新はページ遷移とともに行われる。

(ユーザーによるデータの書き込みが成功したとき、リダイレクトが返答されるように作る必要があった。そうしないと履歴にPOSTリクエストが残り、「戻る」ボタンを押すと再びPOSTリクエストを送ることになる。 たまに「ブラウザの”戻る”ボタンを押さないでください」と書いてあるサイトがあったのはこの問題のため。)

Progressively Enhanced Multi-Page App (PEMPA)#

Progressively Enhanced Multi-Page App (PEMPA, 別名 “JavaScript Sprinkles”)

Progressive Enhancementは、ブラウザが持つ追加機能で体験を向上させるという考え方で、2003年ごろに出てきた言葉

AJAXは2005年には知名度のある言葉となっていた。しかし全員がJSを十分に使えるネットワーク環境である保証はないし、基本的にはMPAをベースにしつつ、JavaScriptはMPAの体験を向上させるためだけに補助的に使われていた。

この時代では、jQueryやMooToolsなどが隆盛を誇っていた。

例:Ruby on Rails + jQuery

Single Page App (SPA)#

<div id="root"></div> が入ったhtmlをCDNから配信して、JavsScriptでコンテンツを埋めていくというスタイル。

フレームワーク側の機能でStatic Site Generation (SSG) などの機能もある

コードの重複が解消されてDeveloper Experience (DX) の向上には寄与したが、PEMPAと同様の問題が残った。

2010年代半ばからSPAが主流になった。

SPAの問題#

  1. バンドルサイズが大きい

  2. データをダウンロードするために、jsのコードを最初にダウンロードしないといけない、という依存関係によるパフォーマンス低下

  3. クライアントサイドのマシンスペックに依存する

  4. 状態管理

Progressively Enhanced Single Page App (PESPA)#

SPAとMPAの長所を組み合わせる、という意味でのEnhanceがなされたSPA

PESPAはブラウザの動作をエミュレートすることで、デフォルトの動作を阻止する。ブラウザでリクエストを行うかJavaScriptでfetchリクエストを送信するかにかかわらずサーバーサイドのコードは同じように動作することを保証する。

サーバーでレンダリングを行い、クライアントでインタラクティブに動作する部分も含めて管理する。

2020年に出たRemixがPESPAを先導するフレームワークであり、他にはSvelteKitなどもPESPAを取り入れようとしている

PESPA の特徴#

  • 基本的な機能 - JSは強化するために使用されるもので、アプリの大部分はJavaScriptなしでも動作する

  • 遅延読み込み + インテリジェントなプリフェッチ (JS コード以上のもの)

  • コードをサーバーにプッシュする

  • UI コードの手動複製がない (PEMPA の場合など)

  • 透過的なブラウザエミュレーション (#useThePlatform)

PESPAが解決したMPAの問題点#

1. ページ全体の更新#

PESPAは、ブラウザのデフォルトの動作を阻止し、代わりにクライアントサイドでJavaScriptを使ってブラウザのエミュレートを行う。

コード上では大した変化がないが、ユーザーの体験は向上する

2. UIフィードバックコントロール#

ブラウザのデフォルト動作を阻止し、fetchリクエストを行う

PESPAが解決したPEMPAの問題点#

1. デフォルトの動作を防ぐ#

PESPA の核となる側面は、ルーティングとフォームに関してブラウザーとほぼ同じように動作すること。

それにより、MPAの(シンプルな)メンタルモデルを実現できる。

2. コードの重複#

クライアントとサーバー間でコードを共有し、ブラウザーの動作をエミュレートする適切な抽象化を行うことで、コードの重複が回避され、また自分で記述しなければならないコードの量が大幅に削減される。

3. コード構成がシンプル#

PESPAにおけるブラウザのエミュレートがもたらすメンタルモデルによって、アプリケーションの状態管理は必要なくなりました。そのため、コード構成がとてもシンプルになりました。 また、ネットワークを挟んだサーバーサイドとクライアントサイドの両側で、同じようにレンダリングロジックが処理されるため、無造作なDOMの変化を引き起こすことはないことが保証されています。

4. サーバーサイドとクライアントサイドの間における間接性#

PESPAがブラウザの動作をエミュレートすることで、フロントエンドとバックエンドのコードのコロケーションが可能となったため、間接性が解消され、生産性が大幅に向上した。

PESPAが解決したSPAの問題点#

1. バンドルサイズ#

PESPAに移行するためには、サーバーが必要となる。つまり、大量のコードをバックエンドに移動できる。

これによって、本当にUIにとって必要なのは次の3点のみとなった:

  1. サーバーサイドとクライアントサイドの両方で実行可能な小さなUIライブラリ

  2. UIインタラクションとフィードバックを処理するための数行のコード

  3. コンポーネントのコード

2. ウォーターフォール#

PESPAの重要な点は、コードを実行しなくても、指定されたURLのコード、データ、アセット要件を特定することができること。

つまり、コード分割に加えて、PESPA はコード、データ、アセットの取得を 1 つずつ順番に待つのではなく、一度にすべてトリガーできる。

また、ユーザーがナビゲーションをトリガーする前にPESPA がこれらのものを事前にフェッチできるため、必要なときにブラウザーがすぐにそれらを返すことができ、アプリの使用体験全体が瞬時に感じられるようになる。

3. ランタイム・パフォーマンス#

PESPAでは、この分野において2つの利点を有しています。

  1. 多くのコードをサーバに移すことで、デバイスが最初に実行するコードの量を少なくできる

  2. プログレッシブ・エンハンスメントのおかげで、JavaScriptの読み込みと実行が終わる前にUIが使える状態になっている

4. 状態管理#

ブラウザのデフォルトの動作のエミュレートは、MPAのメンタルモデルである。

これのおかげで、PESPAのコンテキストでは、アプリケーションの状態管理をほとんど気にする必要がなくなった。

PESPAは、ミューテーションが完了すると、自動的にページ上に存在するデータの再検証を行う(MPAではページ全体を再読み込みすることでこれを行っていた)

参考#