2024/06/30

フロントエンド入門 フロントエンドの歴史

はじめに

ありがたいことに、Webエンジニアになって2年と少しが経ちました。
初めの頃はバックエンドを中心に業務を行っていましたが、徐々にフロントエンドの面からもプロダクトの改善を進めていくことが増えました。
今回は、フロントエンドの入門として、フロントエンドの歴史を整理していきたいと思います。

フロントエンドの歴史

私自身のエンジニア歴がWebの発展の歴史と比べるとはるかに短いため、歴史的な背景については詳しくはありません。

なので、先人の知恵を借りて、フロントエンドの歴史を整理していきたいと思います。

対象はWebが発達し始めた90年代末から2000年代初頭のクラシックSSRの時代から、SPAが主流となる2010年代初頭までの時代を整理していきます。

参考:

MPA(Multi Page Application)クラシックSSRの時代 90年代末 ~ 2000年代

リンクのクリックやフォーム送信などの操作を行うと、サーバーから新しいHTMLが返され、画面が再描画されます。

この時代のWebサイトでは、リンクをクリックすると新しいページに遷移するのが一般的でした。

レンダリングの仕組み
サーバーサイドで動的にHTMLを生成し、クライアントに返す方式で、サーバーサイドレンダリング(SSR)と呼ばれます。 現代ではSPAをプリレンダリングする仕組みもSSRと呼ばれますが、参考元の資料では区別のためにこちらをクラシックSSRと呼んでいます。

この時代のWebページは、サーバーから返されるHTMLが全てであり、クライアント側での操作はほとんどありませんでした。

この時代以前の類似技術として、FlashやJavaアプレットなどがありました。

  • Flash: ブラウザ上で動画やアニメーションを再生するためのプラグイン
  • Javaアプレット: Javaで書かれたアプリケーションをブラウザ上で動作させるための技術

これらは両方ともセキュリティの問題やパフォーマンスの問題がありました。

Flashの利用については、AppleがiOS上でサポートしないと表明したことが転機となりました。(2010年4月)
動作が重く、セキュリティ問題を抱えているFlashはiOS上でのサポートがないということで、Webサイトの開発者はHTML5やCSS3に移行することを余儀なくされました。この時点でのHTML5はまだ草案段階であり、実装状況はブラウザによって異なっていました。

バックエンドの開発

この時代のバックエンドの開発は主にWeb MVCフレームワークを使って行われていました。 例: Ruby on Rails, Struts, CakePHP, Spring-Framework
ビューにはテンプレートが使われました。この時点でのサーバーの役割として、HTMLを生成することが主であり、エンジニアがJavaScriptを書くことは少なかったです。

2000年代の初頭ではPerlの人気が高く、2003年のWordPressのリリース以降PHPが人気を博しました。
その翌年の2004年にはRuby on Railsがリリースされ、Rubyの人気が高まりました。

JavaScriptのAjaxを利用した画期的なプロダクトとして、2005年にGoogle Mapsがリリースされました。
滑らかな無限スクロールを実装するために、JavaScriptのAjaxを利用したことが話題となりました。
この時点ではGoogleは直接JavaScriptを書いていたわけではなく、間接的に生成する形でした。
C++で書かれたコードをJavaScriptに変換するGoogle Web Toolkit(GWT)のようなツールを使っていました。

MPA(クラシックSSR + jQuery)の時代 2000年代 ~

この年代になると、JavaScriptが台頭してきます。

レンダリングの仕組み クラシックSSRで生成されたHTMLにJavaScriptを後付けする形式 この方法では、従来のクラシックSSRで構築されたシステムに導入することが容易でした。

この年代でのフロントエンドの背景として、ブラウザのシェアがIEが圧倒的であったことが挙げられます。 JSやDOMの機能不足で、ブラウザ仕様も標準化されておらず、差異を吸収する高機能なライブラリが必要であったため、jQueryが登場しました。

課題1: アプリケーションの構造

  • 命令的なイベントハンドラ
  • 大量のイベントハンドラが散らばり、処理も散らばる
  • イベントハンドラ間に不明瞭な依存関係が生まれる
  • DOMが巨大で暗黙的なグローバル変数になってしまう

課題2: 開発ワークフロー

  • HTMLはマスタとなるリソースではない
    • Gitで管理するのはHTMLの元になる「テンプレート」
  • JS側が必要とするHTMLを修正するには、テンプレートの修正が必要
    • バックエンドとフロントエンドで開発者が分かれている場合は、コミュニケーションコストが高い

SPA(CSRのみ) 2010年代初頭

この時代になると、SPA(Single Page Application)が登場します。

SPAは、クライアントサイドでのレンダリングを行うことでユーザーエクスペリエンスを向上させることを目的としています。

画面遷移時にサーバーに対して新しいHTMLを要求するのではなく、JSを用いてクライアントサイドで画面を再描画することで、ユーザーの操作に対してリアクティブに画面を更新することができます。

ロードするHTMLページは1つだけで、残りはJSONなどのデータを取得してJSで画面を再描画していきます。

SPA普及の背景として、モバイルデバイスの普及があります。 スマホ向けのネイティブアプリが普及する段階で、WebのバックエンドにはAPIサーバーを用意し、フロントエンドでも同じAPIを利用することで、ネイティブアプリとWebアプリのコードを共有することができるようになりました。

この時代のSPAはクライアントサイドだけでレンダリングし、サーバーサイドではHTMLを動的にレンダリングしません。

このあたりで、SPA向けフレームワークが登場します。 例: AngularJS, Backbone.js, Ember.js, Knockout.js 2010年代半ば以降、React, Vue.jsが登場し、SPAの主流となりました。Vue.jsは日本では特に人気が高いです。

従来のクラシックSSR + jQueryの構造が持っていた以下の課題をSPAは解決します。

  • フロントエンドのアプリケーション構造
    • 以前はHTMLとJSが密結合しており、イベントハンドラ等も散らばっていました
    • SPA登場以降、Model-View-Controller(MVC)やModel-View-ViewModel(MVVM)などの設計パターンが一般的になりました
    • DOMが巨大で暗黙的なグローバル変数になってしまう問題も解決されました
  • サーバーサイドのテンプレートが不要に
    • フロントエンドに関連するリソースは全てフロントエンドで管理されるようになりました
    • これにより開発チームがバックエンドとフロントエンドで分かれていることも珍しくなくなりました

このSPA(CSRのみ)にも課題があります。

1つ目は構造的な問題で、以前のクラシックSSRで構築されたMPAとはアプリケーション構造が大きく異なるため、移行が難しいという問題があります。

2つ目はSEO対策です。クラシックSSRではサーバーサイドでHTMLを生成するため、クローラーがHTMLを取得しやすいですが、SPAではクライアントサイドでHTMLを生成するため、クローラーがHTMLを取得しにくいです。現在はGoogleなどのクローラーはJSをサポートしていますが、それでも不利な状況にあります。この問題についてはSEOが不要なサービスでは問題になりません。関連する問題として、同様の理由でOGPなどのメタ情報も取得しにくいです。

3つ目は初期表示の遅さです。
サーバーから返されるHTMLは空のため、初期表示されるのはJSが実行されてからです。

SPA(CSR + 事前レンダリング) 2010年代後半 ~

  • 最初に配信されるHTMLにはコンテンツをサーバーサイドでレンダリングして埋め込む形のSPA
  • クラシックSSRと違い、事前のレンダリングにはCSRと同じライブラリ、コードを使う
    • 事前レンダリングでは、DOM操作の代わりにHTMLを生成する
    • Isomorphic JavaScript, Universal JavaScript, SSR, Prerenderingなどと呼ばれる
  • 事前レンダリングの実行には、Node.jsが使われる
  • 初期表示の後はSPA(CSRのみ)と同様にCSRで画面を更新する
    • 事前レンダリングの目的は、初期表示の高速化とSEO対策

課題

  • INP(Interaction to Next Paint)が遅い

INPとは
ユーザーの操作が次の描画フレームに影響を与えるまでの時間を測定するウェブパフォーマンス指標です。 言い換えると、ウェブページがユーザーの操作にどれだけ迅速に反応するかを示す指標です。

フロントエンド技術の進化により、事前レンダリングについてもいろんな種類が登場しています。

  • SSR(Server Side Rendering)
    • HTTPリクエスト時にオンデマンドで事前レンダリングする
    • ランタイムのサーバーが必須
  • SG(Static Generation) SSG(Static Site Generation)とも呼ばれます
    • ビルド時に事前レンダリングする
    • ランタイムのサーバーが不要
  • ISR(Incremental Static Regeneration)
    • ビルド時に事前レンダリングするが、リクエスト時に再生成する(SSGとSSRのハイブリッド)
    • ランタイムのサーバーが不要

メタフレームワーク(Next.js, Nuxt.js等)

React, Vue.jsなどのフレームワークをベースにしたメタフレームワークが登場します。 React,Vue.jsをライブラリと呼ぶかフレームワークと呼ぶかで呼称が変わります。

  • React等をライブラリと呼ぶ場合
    • Next.js等はフレームワークと呼ばれることが多い
  • React等をフレームワークと呼ぶ場合
    • Next.js等はメタフレームワークと呼ばれることが多い

まとめ

  • 現代のWebアプリ
    • MPA(クラシックSSR + jQueryまたVanilla JS)
      • 古くからある既存システムやその周辺のサービスに多い
    • SPA(CSRのみ)
      • React, Vue.jsなどのフレームワークが主流
      • ログインが必須のアプリケーションなど、SEOや初期表示の遅さが問題にならないサービスに多い
    • SPA(CSR + 事前レンダリング)
      • Next.js, Nuxt.jsなどのメタフレームワークが主流
      • SEO対策や初期表示の高速化が必要なサービスに多い

所感

私のように、Webの発展以降にエンジニアになって人間にとっては、Webの歴史を知ることは、これからの技術選定のうえでも非常に参考になる点が多いと感じました。
実際に体感している技術の進化と、その背景にある歴史を知ることで、技術の選定や問題解決に対するアプローチが変わることがあると思います。
私のチームでは、バックエンドのエンジニアが中心ではありますが、フロントエンドに関連する負債も多く抱えているため、今後はフロントエンドの知識も深めていきたいと思います。