Webアプリケーション技術スタック比較

Contents

概要

新規にWebアプリケーションを開発する際には多くの場合、ある程度プログラミング言語やフレームワーク等のアプリケーション周りの技術が固定化されてから残りの部分が決められることが多い。

今回はアプリケーション技術の選定は一番最後にして、レンダリング方法やインフラ面を検討しつつ、どのようなWebアプリケーション技術スタック全体を選択するべきか考える。

なお、Webサイトとしてはゲーム等のような体験重視型のサイトではなく、記事サイト等のようなコンテンツ重視型のサイトを想定している。
(販売サイトであれば体験重視型にするかコンテンツ重視型にするかは開発者の意図にゆだねられる。)

つまりWebアプリケーションと書いたが正確には動的コンテンツやインタラクティブ処理を含むWebサイトである。

 

レンダリング方法

Webアプリケーション開発において、いくつかのレンダリング方法がある。

レンダリング方法の選択によって、その他の部分が大きく限定され得るし、ユーザ視点から見ても影響の大きな部分であるので、ここを最初に検討する。

 

SSR (Server Side Rendering)

サーバ側でそのまま表示可能な(あるいはJavaScriptにより多少ブラウザ側で修正する)HTMLを生成してクライアント側に返す方法。

 

メリット

 

デメリット

 

CSR (Client Side Rendering)

サーバはJavaScriptのリンクだけで中身のないHTMLを返す。ブラウザは受け取ったJavaScriptを実行し、JavaScriptは画面全体を描画する。その際に必要に応じて再度サーバよりAPI経由でデータを取得する。
ページ遷移の際も、実際はページ内部でAjaxによりAPIでデータを取得しているだけであり、取得したデータをもとに必要な部分だけを再描画する。場合によっては既に保持しているデータだけで描画可能でサーバとの通信が不要になる。
このような方式から、CSRで作成されたWebサイト(Webアプリケーション)はSPA(Single Page Application)と呼ばれる。

 

メリット

 

デメリット

 

SSG (Server Side Generator)

レンダリングする方法というよりも設計方法に近く、SSG自体は正確にはツールのジャンルである。

SSGを使った構成では、SSRのようにサーバ側で表示可能な状態のページを生成するが、クライアントからのリクエストの都度生成するのではなく、事前に生成しておき、リクエストの際は生成済みのHTMLファイルを返す。ただし、完全に静的コンテンツを返すだけでよいというわけではなく、認証やページ間のデータの受け渡し等が多々発生するので、一部の動的処理が必要になりがちである。

 

メリット

 

デメリット

 

 

どのレンダリング方法が良いか

SSRはフルスタックのWebアプリケーションフレームワークを使用したい場合や、バックエンド構成をシンプルにしたい場合に向いている。ただしそれらは開発者視点でのメリットである。

CSRはページの一部のみが変化する構成が大半のWebサイトで、かつ、SEOを重視しなくてよい場合に向いている。また、スマートフォンでネイティブアプリの代わりとしてWebアプリ(PWA:Progressive Web Apps)化する場合には最適である。開発効率という点ではネイティブアプリよりも有利となり得る。
ただし、実際のところ、CSRの使いどころはあまりない。

SSGはユーザ目線に立った場合最も利点が多い。ただし、技術的にはまだ新しいので製品選定や情報収集等に苦労があるかもしれない。

 

結局のところ、多くのWebサイトは、特にBtoCサイトはますますSEOやFCPの重要性が増していることからSSGを優先的に選択すべきである。ただし、SSGの苦手とする更新頻度が多い、例えばSNS的要素があるサイト等は、更新頻度が多いページのみをSSG以外で構成するという複数の方法を取るのが良い。

なお、SSGを基本としたアーキテクチャをJamstackと呼ぶ。JAMとはJavaScript、API、Markupの頭文字である。

手早く簡単に作りたい場合なんかはフルスタックフレームワークを存分に利用できるSSRであったり、PWAとしてはCSRだったりが、限定的ではあるが最適ではある。

 

APIの構成

SSGでは画面生成処理とデータ取得・保存・加工や演算等の処理を分ける。これは従来のフロントエンドエンジニア領域とバックエンドエンジニア領域で担当するものだからである。

したがって、SSGを採用する場合、画面生成用とは別の、いわゆるバックエンド用のAPIサーバが必要となる。

APIサーバの構成方法として古くからあるサービス指向なAPIアーキテクチャ(gRPCという新しい仕組みも出てきている)や、リソース(エンティティ)指向のREST API方式やGraph QL方式がある。
サービス指向のAPIアーキテクチャを用いることでAPI呼び出しもとの都合に合わせた1つのAPIで概ね全てを解決できる呼び出しもとから見た簡単さというメリットがある。
リソース指向のAPIアーキテクチャを用いることで個々のAPIをシンプルにすることができ、またAPIを利用する側もREST APIの規則に基づいて利用することができるので利用しやすくなるというメリットがある。

 

REST API

HTTPメソッドとURLによってAPIの挙動を決定する。

HTTPの各メソッド(POST、GET、PUT、DELETE)をCRUD操作(CREATE、READ、UPDATE、DELETE)に見立てる。

更にAPIのエンドポイントとなるURLによって操作したい対象データを表す。

例えば”GET /book/3/page/5″というエンドポイントへのアクセスではID:3の本の5ページ目のデータを取得する。

APIは原則としてステートレスとして利用される必要があり、複数のAPIをどの順番で呼んでも結果は同じでなければならない。

 

メリット

 

デメリット

 

 

Graph QL

REST APIにおけるオーバーフェッチの対策を主として設計された。

APIは原則としてステートレスとして利用される必要があり、複数のAPIをどの順番で呼んでも結果は同じでなければならない。

HTTPメソッドはPOSTのみでよく、エンドポイントでデータの取得・保存・削除等を分ける。

APIリクエストとしてJSONに似た専用のクエリを送る。レスポンス自体は通常JSON(XML等もあり得る)である。
例えば以下のような形式で、取得したい項目(属性)を指定している。

{
book(id : 3){
id
name
page(number : 5){
body
link
}
}
}

APIは原則としてステートレスとして利用される必要があり、複数のAPIをどの順番で呼んでも結果は同じでなければならない。

 

メリット

 

デメリット

 

どのAPI構成が良いか

シンプルさで言えばREST APIであるが様々問題があって使いにくい。それらを改善したのがGraph QLであるが、一気に複雑さが増した。

結局のところデータ更新がある程度発生する1サービス(複数のサービス・プロダクトが連携し合わない)で完結するWebアプリケーションにおいては、REST API以前のRPCやFAT APIと呼ばれる1 APIで複雑な処理を行う構成(サービス指向)の方が全体として効率的である。

1 APIで複雑な処理を行う場合、当然API側の複雑さが失われるが、一方でAPI呼び出し元をシンプルに開発できる。API側をシンプルにするということは実質API呼び出し元を複雑にするに過ぎない。SSGにおいて、画面構成処理はHTMLの生成が主目的であり、フロントエンドエンジニアの領域であり、ビジネスロジックやデータの組み合わせやトランザクションについて注力すべきではない。

また、REST APIにしてもGraph QLにしてもトランザクションが分断されがちであるので、データ不整合が発生し得る。データ不整合に別途対処することも可能であるが、多くの場合、そもそもデータ不整合を発生させないように設計する方が楽である。

以上から、比較的小さなシステムの場合はREST APIもGraph QLも使用しない方が効率的である。

ただし、(ほぼ)読み込みのみのAPIしか不要なWebアプリケーションである場合はREST APIやGraph QLについて一考の価値がある。また、外部にAPIを公開しないにしても、多数のエンジニアが関わるような場合(特にフロントエンドとバックエンドの開発チーム間の独立性が高い場合)は規約に基づくREST APIやGraph QLの利点が大きくなることも検討すべきである。
また、APIの数が増えてくると、同じリソースを参照する似たようなAPIが増えてくる可能性があり、見通しの悪さや影響範囲の複雑さが目立ってくる。将来的なスケールを考える場合、このデメリットの負担は大きい。

参考:https://circleci.com/ja/blog/soa-vs-microservices/

参考:https://cloud.google.com/blog/ja/products/api-management/understanding-grpc-openapi-and-rest-and-when-to-use-them

 

技術スタック選定

上述したようにアーキテクチャとしてはSSG・SSR+API群の構成とする。

 

レンダリング(画面構成)部分の技術

SSGとして利用できるものは様々あるが、最低限SSGとして必要な機能は以下がある。

さらに追加で以下機能もあればよい

この中で最も影響が大きいのがテンプレートエンジンで、テンプレートエンジンの使いやすさが開発効率やテストのしやすさに影響する。
例えばHTML中にプログラムを書くのではなく、プログラム中にHTMLを書くようなテンプレートエンジンだとフロントエンドの切り離しが十分にできずに、プログラムがわからないとフロントエンドの実装ができなくなる。
反面、1ページを1ファイルに集約して書かなければならないようなテンプレートエンジンだとヘッダー等の共通部分の切り出しが出来ずにメンテナンスが大変になる。

そしてここで初めてどのプログラミング言語にするかも考慮する。SSGではテンプレートと共に使用する動的部分や、クライアントからの要求に動的に応答するAPIにおいてもプログラミングが必要になってくる(後者は別システムとして切り出しも可能)。そのため、ここで各開発言語の特性を考慮するとよい。

SSGとしてどのような製品が使用できるかはこちらで一覧化されている。基本は人気の(GitHub Starsが多い)ものから選択したほうが、情報量やエンジニアの確保の面で有利である。

 

テンプレートエンジンについて

2023年1月時点で一番人気のSSGツールはNext.jsである。これはフロントエンドフレームワークのReactをSSG / SSRとしてサーバサイドで使用できるようにしたものである。なお、3位のGatsbyも同様にReactをテンプレートとして用いるものである。ただReactは元々はCSRを行うためのものであり、今回のように過去の資産を活かしたい・既存技術者のコンバートが楽などの技術的制約がない場合において、あえてReactベースのテンプレートを選ぶ理由はない。ReactはJSXというJavaScriptを前面に出した形式でテンプレートを記述するので、普通のHTMLから比べると複雑さが大きい。

例として下記のように、ReactのJSX形式では関数の戻り値としてHTMLを返すように記述する。

render() {
return <h1>Hello World</h1>;
}

Reactの最も得意なCSRを原則使用しないのであれば、学習コストも比較的高いReactベースのNext.js等は却下する。

 

2023年1月時点で二番人気はHugoである。これはGo言語ベースでの製品であるが、テンプレートエンジンは一般的なHTML中に変数を括弧でくくって書くようなタイプであり、全くGo言語らしさがない。そのためGo言語を意識しなくてよいとっつきやすさがあるが、HugoはSSG専用でSSRは出来ない。SSG部分とSSR部分を分断して構築するならよいが、そうでないならHugoでは実現できないため、こちらも却下。仮にSSG部分とSSR部分を分断するにしても最低限同じテンプレートエンジンを使用できるようにしたい。

 

以上より上位の3位までが却下になり、4位以下は3位以上と比べると著しく人気に差があるというわけではない。

製品の人気度合いは製品の今後の発展性等に影響を与えるので重要な指標であるが、その点で比較できないのであれあば、他の基準で選択しなければならない。

ただ、近年登場したアイランドアーキテクチャは次で説明するが有用な仕組みである。アイランドアーキテクチャを使用可能であれば積極的に採用したい。

 

アイランドアーキテクチャ

アイランドアーキテクチャとはHTMLの画面全体をいくつかのコンポーネント(アイランド:島)に分割し、アイランド単位で事前にレンダリングするか、クライアントからの呼び出し時に都度サーバサイド or クライアントサイドでレンダリングするフロントエンドのアーキテクチャである。

アイランドアーキテクチャによってSSRを必要とする(完全なSSGができない)ページにおいても部分的にSSGを導入できる。

また、必然的にコンポーネントベースでの開発となるので、再利用性が高まり、単体試験も行いやすくなる。

なお、クライアントからの呼び出し時にレンダリングすることをハイドレーション(Hydration:給水)と呼ぶ。稀に給電とも呼ばれる。

参考:https://www.patterns.dev/posts/islands-architecture/

 

2023年2月時点ではまだアイランドアーキテクチャをサポートしているSSG・SSRツールは少ない。
有名どころでは以下しかない。いずれもJavaScript製品である。

 

ルーティングについて

SSGにおけるルーティングについてもクライアントサイドでルーティングを行うものとサーバサイドでルーティングを行うものが存在する。

SSGといっても(インタラクティブな部分がない場合に)完全にJavaScriptのない静的ページを生成できるツールと、部分的な事前レンダリングをサーバサイドで行って、クライアントサイドで残りのレンダリングを行うツールがある。後者のようにすることで、クライアントサイドでのルーティングが可能になり、ひいてはCSRの強みである、高速なページ遷移が実現できる。

つまりSSGのFCPの高速性と、CSRの2ページ目以降の高速性の両取りを狙っている。

ただしこれにより、完全にJavaScriptのないSSGよりかは遅くなり、複雑性が増す。

今回の選定においてはよりシンプルさは志向してサーバサイドでのルーティングを行える製品を選ぶ。

 

言語ごとの指標

基本はSSGとしての機能の充足や利用のしやすさを優先的に考えるべきであるが、ある程度はモダンで有用な言語のものから選択したほうが良い。指標として参考になるものには以下がある。

上記に加え、原則として保守性の高い静的型付けができる言語から選択したほうが良い。

以上を勘案すると以下言語から選択したほうが良い。

いずれもコンパイル言語という点で実行の容易さという点には難点がある。ただし、TypescriptについてはNode.jsに代わってDenoという実行環境が登場しており、そちらでは内部で自動でコンパイルするのでTypescriptのまま実行できる。Denoはほかにもパッケージ管理の複雑さなどNode.jsの問題を解決しているが、一部Node.jsパッケージが動作しないという問題もある。

 

以下は除外した言語とその理由である。

 

フロントエンド比較結果

JavaScript用の製品であってもTypescriptを確認するとサポートしていることがある。

よって、Java、Typescript、JavaScriptのSSGから以下条件を満たすものを検討した。

 

結果としてAstroが最もよさそうである。

JavaScript製のAstroは公式にTypeScriptをサポートしているし、その他の必須条件も満たしている。
ただし、アイランドアーキテクチャではあるが、ISRではない。ISR化する仕組みの導入か大規模サイトとなるとビルド時間増加に耐えなければならない。

また、Denoをサポートしており、テンプレートエンジンは外部のものを組み込めるが、標準搭載のテンプレートエンジンも十分に使いやすい。

参考:astroの使用感について紹介

 

API部分の技術

APIはレンダリング部分がTypeScriptで開発することを受けて、TypeScript周りの技術を使用する。

AWS Lambda等のFaaS (Function as a Service) は原則コールドスタンバイであり、確実な応答性能が確保できないため、選択肢から除外する。
※AWS Lambdaであれば、Javaについてのみウォームスタンバイの機能がリリースされた。
※Azure Functionsであれば、実行環境を占有する(実行時間単位の課金でなく、使用時間単位の課金となる)プランであればウォームスタンバイが可能である。

 

メモ

その他のWebアプリケーションフレームワーク

WebアプリケーションフレームワークにはSSRのものを初めとして多数存在する。

有名どころの一部を記載する。

 

用語

 

PHP

なお、PHPから派生したHackという言語がある。現時点では互換性は完全ではなくなったが、記法は似ている。
独自の実行環境(HHVM)により、当初はPHPの実行を高速化するためのものであったが、PHP7以降はPHPも高速化されたため、Hackの現在の主なメリットとしては静的型付けにある。しかし、HackはHackでPHPと大体は同じとは言えネット上に情報が少ない。
Hack(HHVM)はPHPコードの大半をそのまま実行可能なので、PHPフレームワークをHackでも使用可能である。ただし、フレームワーク自体はPHPなので、フレームワークとユーザコードがやり取りする部分は静的型付けを使用できない。

 

Laravel

現在PHPで最も使用されているフレームワークである

大規模システムで性能が良い。反面、自由度が高いが大規模開発だと規約が必要となる。

学習コストは低い。

パフォーマンスが他のPHPフレームワークと比較して悪い。特にメモリ使用量が多い。

 

CakePHP

Ruby on Railsの影響を強く受けている。

現在はLaravelに人気は抜かれているが、稼働しているシステムでは依然CakePHPの方が多いと言われている。

小規模開発ではスピーディに開発できる。制約が多いため、使用者が規約を定める必要は低い。

反面、大規模システムでは性能が悪くなる。また、制約が多いため、自由度は低い

 

Symfony

Ruby on Railsの影響を強く受けている。Laravelに次いで開発者数が多い

 

CodeIgniter

日本では使用は少ないが、海外では使用が多い。応答速度が良い。

保守性が低いと言われる。

 

Laminas MVC (旧Zend Framework)

以前はZend Frameworkという名前で開発されていたがLaminas Projectとして引き継がれた。Laminas Projectは複数のプロジェクトからなり、WebアプリケーションフレームワークはLaminas MVCである。

オブジェクト指向を徹底して使用している。

記述の自由度が高い。現時点ではZend Frameworkはともかく、Laminas MVCの情報は少ない

 

Phalcon

軽量で高速に動作する(C言語で実装されている)。PHPのフレームワーク中で断トツのトップである。
現時点では、それほど人気がない

 

Slim

それほど人気がない

 

Yii

それほど人気がない

 

FuelPHP

専用コマンドが用意されており開発をサポートする。現時点では更新が止まっており、既にあまり人気がない

 

Flight

それほど人気がない

 

Python

 

Flask

現在Pythonで最も人気のあるフレームワーク。

マイクロフレームワークであるが、拡張機能が多く必要機能だけを選択してフルスタック化できる

 

Django

Flaskの人気が上昇する前はPythonで最も人気のあるフレームワークだった

 

FastAPI

Node.jsのような非同期処理を行う。DB等のI/Oで後続処理を待つ場合などに独特の記述が必要となるが、パフォーマンスが非常に高い。

静的型付けのないPythonにおいて関数の引数と返り値に型を付けることができる。

 

Tornado

Node.jsのような非同期処理を行う。DB等のI/Oで後続処理を待つ場合などに独特の記述が必要となるが、パフォーマンスが非常に高い。

 

 

Ruby

Rubyといえば、Ruby on Railsというくらいに、ほかの用途ではあまり使用されていない。

一応、Sinatraなどの他のフレームワークも存在する。

 

Ruby on Rails

フレームワーク自体に命名規則などの標準的な規約が定められており、その規約に従う限り、個別の設定が不要となる。そのため、その規約を学習しなければ使用が難しいが、学習すれば開発効率が高まる。

 

Java


Spring Framework

依存性注入という機能があり、フレームワークに必要なインタフェースを実装するクラスを設定により変更できるので、システム実行時に任意の実装クラスに差し替えができる。これにより、個々の実装クラスの独立性を高め、単体試験等を容易にする。

 

Struts

以前は人気のあるフレームワークだったが、脆弱性が多発したため現在は使用が減ってきている

 

Scara

オブジェクト指向プログラミングと関数型プログラミングの両方の記法ができる。その分難易度が高い。

またJVM上で実行でき、Javaのコードも扱える点も特徴である。

 

Play Framework

 

Go

機械語へのコンパイル型言語のため、動作が高速。例外処理がないため、エラーハンドリングとメイン処理を明確に分岐できない点は難点。

静的型付けを行うが、コンパイラが型を推論するため、明示的に型を指定しなくてもよい。ただしその場合、人にとっては型を読み取りづらくはなる。

 

Ehco

RESTful API用のマイクロフレームワーク

 

Revel

 

Gin

歴史が古く人気がある。

軽量でHTTPルーターのレスポンスが速い

 

Beego

学習コストが低い

 

Goji

 

iris

Node.jsでいうところのexpressjsを標榜している。

最速のWebフレームワークを目指している。

 

hugo

SSG用のフレームワーク

 

JavaScript

バックエンドのJavaScriptはNode.jsという実行環境によって実行される。

フロントエンドのJavaScriptとは違いがあるものの、バックエンドとフロントエンドを同じ言語で開発できるのが利点と捉えられている。

 

NestJS

TypeScriptを基本とする。まだ日本での利用実績は少ない。

 

Nextjs

ReactというCSR用のフロントエンドライブラリをNode.jsによりサーバサイドでもSSRとして使用できるようにしたものである。

 

Nuxtjs

VueというCSR用のフロントエンドライブラリをNode.jsによりサーバサイドでもSSRとして使用できるようにしたものである。

 

Typescript

TypeScriptはJavaScriptにオブジェクト指向と静的型付けを加えた言語で、コンパイルしてJavaScriptの変換してから実行される。
JavaScriptのライブラリに対して型情報だけを付与することもできる。

TypeScriptのフレームワークはJavaScriptでも開発できるし、JavaScriptのフレームワークはTypeScriptでも開発できる。

 

fresh

https://jamstack.org/generators/fresh/

一番人気のSSG。deno公式のSSGなので、denoで動作することも保証されている。
ただし、テンプレートがJSX形式であり使いにくい。

 

Scully

https://jamstack.org/generators/scully/

公式サイト:https://scully.io/

フロントエンドフレームワークのAngularをSSGに対応させたもの。というよりかはAngularアプリを入力としたSSG。従ってフルセットのAngular開発が必要。

Angularはテンプレートエンジンとしてみれば割と素直であるが、Angularアプリとしてビルドが必要だったりと一定のAngular知識が必要であり、導入の敷居はそれなりに高い。

 

iles

https://jamstack.org/generators/iles/

公式サイト:https://iles.pages.dev/

テンプレートにはいくつかのものが使用されるが、基本はVueが推奨されている。
ドキュメントもVueを使用している前提のものが多いので、この製品を使用するのであればVueを使用したほうが良い。

Vueはテンプレートエンジンとしてみれば割と素直であるが、基本的にCSR用のため、やや扱いづらい。

参考サンプル

 

Codedoc

https://jamstack.org/generators/codedoc/

 

Hydrogen

https://jamstack.org/generators/hydrogen/

 

Capri

https://jamstack.org/generators/capri/

 

Staart Site

https://jamstack.org/generators/staart-site/

 

Amagaki

https://jamstack.org/generators/amagaki/

 

INTUITION.DEV

https://jamstack.org/generators/intu-dev/

公式サイト:https://intuition-dev.github.io/intuDocs/#/README

SSGツールというよりかは非開発者向けのローコードツールである。

 

Stasis

https://jamstack.org/generators/stasis-generator/

公式サイト:https://getstasis.com/

まだアルファ版で本番環境での使用は推奨されない

 

Zox

https://jamstack.org/generators/zox/


Notice: Trying to get property 'queue' of non-object in /usr/local/wordpress/wp-includes/script-loader.php on line 2876

Warning: Invalid argument supplied for foreach() in /usr/local/wordpress/wp-includes/script-loader.php on line 2876