クモのようにコツコツと

フロントエンドエンジニア イイダリョウの技術ブログ。略称「クモコツ」

ExpressとJSフレームワーク(React、Vue、Angularなど)との関係について調べたこと

Node.jsのフレームワークExpress。存在は前から知っていたけどイマイチ何ができる物なのかわかっていなかった。以前の記事でRest APIについて調べたことをキッカケに、ExpressとJSフレームワーク(Vue、React、Angularなど)の関係についても調べました。それではいきましょう!

【目次】

※参考:REST APIとは何かを調べまくったらようやくイメージができてきたのでまとめた - クモのようにコツコツと

Expressを習得するためにやったことまとめ
qiita.com

これまでのあらすじ(Node.jsは触っていた)

ExpressはNode.jsのフレームワーク。Node.jsについては既に事始めていた。

サーバサイドJSということでPHP、Python、Rubyに続く流れでインストール→REPL→ハローワールドしている。が、この時点ではNode.jsで何ができるのかあまり理解できていない。

※参考:初めてのNode.js:インストール確認、REPL、Hello worldまで - クモのようにコツコツと

その後、メタ言語(テンプレートエンジン、AltCSS、AltJS)のコンパイル、Gulpのビルド、Webpackのバンドルなど、フロントエンド開発にNode環境が必要なことがわかってくる。これはどちらかというとローカル環境の話。

※参考:フロントエンドのモダンな開発環境を作るために調べていること(追記あり) - クモのようにコツコツと

JSフレームワークVue.jsの拡張機能、Vue CLIを開発するにもNode環境が必要なことがわかってくる。

※参考:【Vue.js】Vue CLIをインストールしてみる(CDN、Nuxe.jsとの違い) - クモのようにコツコツと

Vue.jsベースのNuxt.jsはSSR(サーバサイドレンダリング)を行うため、本番環境にもNode環境である必要がありそう。(ReactではNext.js、AngularではUniversalが同じ位置づけらしい)

※参考:【Vue.js】Nuxt.jsで何ができるのか調べた(SSR、ルーティング、静的ファイル生成など) - クモのようにコツコツと

その後、開発環境としてNode.jsを利用していたが、REST APIによるバックエンドとフロントエンドの分業体制について調べた時、Node.jsの拡張機能であるExpressやJSON-Serverの存在を知る。

※参考:REST APIとは何かを調べまくったらようやくイメージができてきたのでまとめた - クモのようにコツコツと

Expressを使えばJSだけでREST APIが作れるのかな?

ExpressとNuxt.jsの違いって何?

さて、ここで疑問に思ったのはExpressとNuxt.js、Next.js、Universalなどの位置づけ。Expressが何に使える物かわかっていない状態だとこんなイメージになる。

  • Express=Node.jsのサーバサイド環境で何か(?)をする
  • Nuxt.jsなど=Node.jsのサーバサイド環境で何か(SSR?)をする

はて、これって被っているの?被っていないの?Expressを使えばSSRもできるの? ExpressだけでWebアプリは作れるの?逆にNuxt.jsを使えばExpressは不要なの?

SSRとは何か

まずSSRがわかっていない。SSRとは何か。

「サーバーサイドレンダリング」とは一体なんでしょうか?混乱を避けるため厳密な説明は避けますが、少なくとも私たちWebデベロッパーのここ数年の文脈においては、 「(元々ブラウザ上でしか動かなかった)JavaScriptをサーバー内部で実行して、HTMLを生成すること」を指します。
これによって初期表示の際にユーザーが待たされることがなくなるなどのメリットがあります。

※参考:ユーザー体験を向上させるサーバーサイドレンダリングJavaScript — 歴史と利点 - Sundaycrafts - Medium

ふむふむ、Vue.jsやReactがSPA(シングルページアプリケーション)として行っている仮想DOMなどのHTMLレンダリングをクライアントサイド(ブラウザ上)ではなくサーバサイド(Node環境)で行うイメージかな。

こちらの記事では静的HTMLとSPAとSSRを比較している。さらにプリレンダリングというのもあるらしい。

  • SPA:クライアントサイド(ブラウザ)でレンダリング
  • SSR:サーバサイド(Node環境)でレンダリング
  • プリレンダリング:ビルド時にレンダリング

※参考:SPA、SSR、プリレンダリングの違いをまとめてみた - Qiita

HTMLレンダリングをどこで行うかで変わるらしい。

SSRとパフォーマンス

SSRを使う理由としてパフォーマンス改善がある。サーバ上でのレンダリングはパフォーマンスにどのような影響が?

HTTPとは何か

HTMLレンダリングと言われてもいまいちイメージできないのは、そもそものHTTPの通信が理解できていないためだな…。

まず、HTTPとは何か。

Hypertext Transfer Protocol (HTTP) は HTML などのハイパーメディア文書を転送するためのアプリケーション層プロトコルです。

※参考:HTTP | MDN

ふむふむ。HTMLがハイパーテキストであることはわかる。リンクを押すと別のページにジャンプできるのがハイパーなんだよね。

※参考:【Webの基礎知識】書ける前に読む!HTML、CSS、JSの書式-1 - クモのようにコツコツと

ではプロトコルとは何か。

プロトコル(英:protocol)とは
お約束事のこと。
ただし、多くの場合は
「通信する上でのお約束事」を意味する「通信プロトコル」の省略表現
です。

※参考:https://wa3.i-3-i.info/word11.html

通信プロトコルはHTTP以外にもFTP(データ)、TCP/IP(通信)、SMTP(メール)などがある。PはプロトコルのP。

※参考:https://wa3.i-3-i.info/word1254.html

HTTPはWebページを通信するときの約束事。クライアントサイド(ブラウザ)がサーバサイド(Webサーバ)に「このページおくれ」とリクエストすると「ほら、ページだよ」とレスポンスが返ってくる。

※参考:https://wa3.i-3-i.info/word165.html

「このページおくれ」の部分を「HTTPリクエスト」という。下記の3部構成。

  • リクエストライン
  • ヘッダ
  • (空行)
  • メッセージボディ

※参考:https://wa3.i-3-i.info/word1841.html

「ほら、ページだよ」の部分を「HTTPレスポンス」という。下記の3部構成。

  • ステータスライン
  • ヘッダ
  • (空行【CR+LF】)
  • レスポンスボディ

※参考:https://wa3.i-3-i.info/word1842.html

HTTPリクエスト/レスポンスはターミナル(黒い画面)のcurlコマンドで見ることができる。

※参考:HTTPリクエスト/レスポンスの構成要素を初心者にも分かるように解説してみた - Qiita

HTTPレスポンスのステップ

HTTPレスポンスは何段階かステップあって、このような流れになる。

  • Navigation Start:サーバーへリクエストします。
  • First Contentful Paint:ロケーションインジケータがぐるぐる回る段階です。
  • First Meaningful Paint:意味のある情報が表示されます。(画像等はまだです)
  • Visually Ready:画像などが読み込まれてレイアウトされます。
  • Time to interactive:JavaScriptがロードされ実行可能になります。
  • Fully Loaded:すべてが読み込まれて操作可能になります。

※参考:Webフロントエンドとサーバーサイドの技術動向をざっくり整理する/JavaScript - "BOKU"のITな日常

SSRとHTTPレスポンス

SSRが担うのは先ほどのHTTPレスポンスの最初の2つ、Navigation StartとFirst Contentful Paint。それ以外の部分のパフォーマンス改善にもService WorkerやHTTP/2など色々な方法がある。(画像ファイルのサイズ圧縮も含まれるはず)

じゃあServer Side RenderingにおけるFirst Viewのパフォーマンス改善とはどこを指すかというと、「Navigation Start」から「First Meaningful Paint」までです。

で、First Meaningful Paintから先の改善のやり方には、Service Workerを使うとかHTTP/2を使うとか、いろんなやり方があります。 なのでFirst View Performance全体の改善にはいろいろある、ということを覚えておいてください。

※参考:Server Side Renderingについて知るべきこと。Server Side Renderingとは何か? それによって何が改善されるのか?(前編) ng-japan 2017 - Publickey

SSRとSEO

SSRを使うもう一つの理由にSEO対策がある。GoogleはSPAのページもクロールしてくれるが100%正確に読み込まれる保証はない。

Googlebotの特徴として、
GooglebotのJSエンジンが古い
このことから、動的に更新されたjs部分を、 クローラーが正しく評価できているかわからない問題が存在します!

※参考:SPAを導入する際に必要だったSEO対策についての話 -SSR? Prerendering?- - Qiita

またGoogle川のクローラビリティ的にもクライアントサイドでのレンダリングは負担になっている。

現在多くのサイトがJavaScriptベースになっているため、次のステップとしてはJavaScriptのレンダリングも必要となり、ページが一度レンダリングの待ち行列に追加されます。リソースが空き次第、ヘッドレスブラウザのような別サービスである「ウェブレンダリングサービス」(WRS)を使用し、JavaScriptを実行します。

※参考:SSRは必要?Javascriptで構築したSPAサイトのSEOを考える | codit

この対策として「ダイナミック レンダリング」というのが加わるらしい!ページの描画とは別にGoogle botのクロール用のページ情報をレンダリングする。

※参考:JSサイトのための第4のレンダリング構成としてダイナミックレンダリングをGoogleが発表 #io18 #io18jp | 海外SEO情報ブログ

SSR必要?不要?(まず体験が必要)

調べるとSSR不要論も結構ある。実装するハードルの高さもあるし、WebサーバをNode環境でいけるのか?というのもある。

※参考:サーバーサイドレンダリング不要論 - Qiita

ここら辺は自分はそもそもSSRがどんなものなのかわかっていないので比較材料がない。まずは体験してから判断したいと思う。

SPAはシングルページにあらず?

さて、では他のレンダリング方式はどうなんざんしょ。

SPA(シングルページアプリケーション)というと、ページ遷移しない単一ページで、ページ内の変更部分だけ非同期に通信して差分の表示を切り替えるイメージを持っていた。

しかし、実際はURLをルーティングで変更し、History APIで閲覧履歴にも残る、あたかもページ遷移をしているようなUXを提供できる!

※参考:SPAのルーティングの話

そう考えるとSPA=シングルページというイメージは改めてる必要がある。

複数ページサイト=SSR、ではなくUX(SEOやパフォーマンスの以外)だけで見るとSPAとSSRに差異はないということか。

ただ、サーバサイド(Webサーバ)とクライアントサイド(ブラウザ)間での「ページ単位」でのHTTP通信は最初の一回になる。これが「シングルページ」たる所以。

ちなみにSPAで行われるレンダリングを「CSR(クライアントサイドレンダリング)」といい、SSRの本来の対義語は正確にはこちらが正しいらしい。

※参考:SSR, CSRについてのメモ | Qrunch(クランチ)

プリレンダリングとは何か

プリレンダリングについて調べると静的サイトジェネレータ(静的CMS)なんかがこれにあたるらしい。

静的サイトジェネレーターを使えば、データベースが不要になり、一般的にページの読み込み速度も上がるとされています。

静的サイトジェネレーターとは、Markdownなどで書かれたファイルをもとに、静的なコンテンツのテンプレートだけでビルドを行いサイトを作成するためのWebサイト作成用のフレームワークです。

※参考:WordPressの代わりになる!2018年注目の静的サイトジェネレーター6選|ferret

JS系ではReactベースの「GatsbyJS」が定番ぽい。本文の部分はマークダウンでプリレンダリングする。これを「JAMスタック(jamstack)」というらしい!

Jamstack は「JavaScript」「API」「プリレンダリングされた Markup」の3つの要素を持ちます。「Jam」の「J」が「JavaScript」、「a」が「API」、そして「m」が「Markup」です。また、Jamstack は Web サーバに依存しないという特徴があります。

Jamstack、名前がカッコいいw

  • J: JavaScript
  • A: API
  • M: Markup

※参考:Gatsby と Netlify で Jamstack 構成のブログサイトを作ろう - to-R Media

ExpressとREST API

SSRはREST APIではない!

先ほど引用したSPA、SSR、プリレンダリングの比較記事にもう一つ重要なキーワードを見つけた。

実際、ここ一年で私が関わった関わった3つのプロジェクトのうち、2つでSPAによる開発とし、さらにそのうちの1つをアイソモーフィックJavaScriptで開発しましたが、バックエンドはAPIを返すだけでよくなったためロジックやパフォーマンスチューンに集中することができ、フロントエンドはバックエンドの組み込みやテンプレートの準備などを待たずに開発ができるようになりました。

※参考:ユーザー体験を向上させるサーバーサイドレンダリングJavaScript — 歴史と利点 - Sundaycrafts - Medium

「アイソモーフィックJavaScript」はSSRを意味する(SSRという言葉ができる前はこう呼ばれた)。SSRやSPAでサイトを作ると「バックエンドはAPIを返すだけでよくなった」と。これってつまりREST APIの「JSONを返す」ということ!

※参考:REST APIとは何かを調べまくったらようやくイメージができてきたのでまとめた - クモのようにコツコツと

そうか、SSRはあくまでHTMLの生成(レンダリング)をサーバサイドで行うだけであり、JSONデータを返すことは行わないと!

ExpressでREST APIを作れる!

HTMLのレンダリングをどこ(SPA、SSR、プリレンダリング)で行うとしても、REST APIによってデータをJSONを返してもらう必要はある。その部分はバックエンドのフレームワーク(PHPのLarabelやRubyのRuby on Railsなど)の領域になる。

どうやらこのAPIを作る部分をExpressが担っているらしい!ExpressはWebサーバやAPIを作れる。

Node.jsにはExpressという有名なモジュールがあります。Expressを使えば、簡単にウェブサーバを立てることができます。静的ファイルを配信するだけの簡単なウェブサーバから、APIを持つような複雑なサーバまで自由自在です。

※参考:Node.jsとExpressでWeb APIを作ってみよう

Node.jsの「モジュール」とはnpmでインストールできる追加機能のこと。Expressもその中の一つ。

node moduleとは、Node.jsでnpmコマンドを使用してインストールすることで利用できる便利な機能が実装済みのモジュールです。

※参考:Node.jsでモジュール(module)を作成する方法【初心者向け】 | TechAcademyマガジン

「Webサーバ」とはHTTPリクエストに対してHTTPレスポンスを返す仕組み

クライアントとサーバーの間では「リクエスト」と「レスポンス」がいったりきたりすることになる。 ブラウザーが見に行っているサーバーが「Webサーバー」だ。Webに関するサービスを提供しているから、Webサーバーとなる。

※参考:サーバー構築とは|パソコン教室・資格講座なら【KENスクール】

Webサーバを「立てる」とはWebサーバを「構築する」こと。

※参考:"サーバを立てる"とはどういう意味でしょうか? - ... - Yahoo!知恵袋

ExpressはWebサーバを構築するnode module、と。

Exprsessのミドルウェアとは

バックエンドフレームワーク(RailsやLarabelなど)はAPIからJSONを返すだけでなく、HTMLのテンプレート部分の作成も担う。Expressがこれらと同じ位置づけになるとすると、テンプレート部分はVue.js(Nuxt.js)やReact(Next.js)とかぶるのではなかろうか?という疑問。

Nuxt.jsはExpressの中でミドルウェア的に使う

Nuxt.jsはExpressの中で、1つのmoduleとして使用します。  

いままでVue.jsなどでSPAを作るのに慣れていると、フレームワークをモジュールとして使うという発想はなかったかなと思います(自分はなかった)。
この考え方の切替が結構大事かなと思います。

※参考:実際Nuxt.jsとExpressでどうやってSSRやるか理解してましたか?自分はよくわかってなかったです【解説】 - Qiita

はて?ミドルウェアとはなんぞ?

よくexpresssの公式サイトとかで

ミドルウェアを作成します。

 とか、

サードパーティのミドルウェアを使用します。

 とかが見られるのじゃけれど、いかんせんミドルウェアがよくわからんのじゃあ・・・

※参考:expressは一体何をしとるんじゃ・・・ - Qiita

まさにこんな気分。(Expressは何をしとるんじゃぁ!!というタイトルもw)

公式サイトによると

ミドルウェア 関数は、リクエストオブジェクト (req)、レスポンスオブジェクト (res)、およびアプリケーションのリクエストレスポンスサイクルにおける次のミドルウェア関数に対するアクセス権限を持つ関数です。次のミドルウェア関数は一般的に、next という変数で表されます。

ふうむ、わからん。。もう少し読む。

ミドルウェア関数は以下のタスクを実行できます。

  • 任意のコードを実行する。
  • リクエストオブジェクトとレスポンスオブジェクトを変更する。
  • リクエストレスポンスサイクルを終了する。
  • スタック内の次のミドルウェアを呼び出す。

※参考:Express アプリケーションで使用するミドルウェアの作成

こちらの記事がわかりやすそう。

Express.JSでは、複数のURLパスへのリクエストに対して行う処理をミドルウェアというまとまりにして、リクエストレスポンスサイクルの中間に配置することができます。ミドルウェアはいくつでも登録・実行させることがき、連続したミドルウェアのことをミドルウェアチェーンと呼びます。

ミドルウェアには以下のタイプがあります。

  • アプリケーション・レベルのミドルウェア
  • ルーター・レベルのミドルウェア
  • Express本体に標準装備されたミドルウェア
  • サード・パーティー・ミドルウェア

※参考:【NodeでWebアプリ】(5) Expressミドルウェア | OTA TECH BLOG

この「サード・パーティー」にあたる部分がNuxt.jsやNext.jsなのかな。

React、Vue、AngularとExpressの連携

ここら辺は読み込んではいないが今後やりたいことのキーワードとしてまとめておく。

VueとExpress

SSRを使わないSPAの場合はVue.jsとExpressを連携する。

※参考:vueとexpressでSPAを作る - Qiita

先ほどのNuxt.jsのExpressの連携。

※参考:実際Nuxt.jsとExpressでどうやってSSRやるか理解してましたか?自分はよくわかってなかったです【解説】 - Qiita

SSRはVueだけでもできるぽい。

※参考:Vue.jsでSSR(サーバサイドレンダリング)する - Qiita

ReactとExpress

ReactとExpressと連携。

※参考:初級JavascriptフルスタックエンジニアのためのReactとExpressの同時開発チュートリアル(基本的なアプリ作成と同時開発環境構築編) | Casual Developers Note

ReactのSSRでNext.jsとExpressを連携。

※参考:https://kuriyama-blog.com/articles/nextjs-express-api-server-component

SSRはReactだけでもできるぽい。

※参考:React+ExpressでSSRしてみる +α with TypeScript - Qiita

AngularとExpress

AngularとExpressの連携

※参考:Angular7+Express.js 環境を1から構築してみる - Qiita

AngularのSSR、UniversalとExpressの連携

※参考:Angular Universal の Web サーバを Express でサクッと作る方法 - Qiita

MEANスタックとは(LAMPとの比較)

先ほどJAMスタックというのが出てきたけど、 AngularとExpressの連携を調べているときに似た言葉で「MEANスタック」というのもあった。

よく知られるのは「LAMP環境」

  • OS:Linux
  • Webサーバー:Apache HTTP Server
  • データベース:MySQL
  • プログラミング言語:PHP/Perl/Python

これに対して「MEANスタックは

  • M:MongoDB(ドキュメント指向データベース)
  • E:Express(Node.js上で動作するMVCフレームワーク)
  • A:AngularJS(フロントエンドのJavaScript用MVWフレームワーク)
  • N:Node.js(サーバーサイドJavaScriptの実行環境)

※参考:Angular Universal の Web サーバを Express でサクッと作る方法 - Qiita

LAMPの「L」に当たるOSへの言及がないので、OSは自由という理解でいいと思う。

LAMPの「A」はMEANではNでNode環境。サーバ上でJSを実行できる。

LAMPの「M」はMEANでもMでMongoDB。JSONライクなDB!Node.jsと相性がいいのはよくわかる。

※参考:https://kageura.hatenadiary.jp/entry/2018/01/08/MongoDB%25E4%25BA%258B%25E5%25A7%258B%25E3%2582%2581%25E3%2580%2582%25E5%2580%258B%25E4%25BA%25BA%25E7%259A%2584%25E3%2581%25BE%25E3%2581%25A8%25E3%2582%2581

そしてLAMPの「P」の部分がMEANではJSになる。

なお、MEANの「E」「A」の部分がLAMPでは言及がない。これはバックエンドのフレームワークであるLaravel(PHP)やRails(Ruby on Rails)が該当すると思う。

そしてこの「A」が今ではAngularだけでなくReactやVueという選択肢も出てきたということか!

MVC、MVWフレームワークとは

MEANスタックにおいてExpressの役割は「MVCフレームワーク」とあった。

MVCも良く聞く概念。Laravelなんかでも出てきた。

MVCはデザインパターンの1つで、機能ではなく、コードをキレイに管理するための考え方である

MVCは「Model」「View」「Controller」の頭文字をとったもので、実装する機能に応じてファイルを「Model」「View」「Controller」に分ける

※参考:MVCの概念を理解する【Webフレームワークの基礎知識】 | Web白熱教室

ふむふむ。どちらかというとコードの機能と構造の関係を表す部分なわけだ。

一方AngularはMVWフレームワークだと。MVWとは何だろう。

MVについて議論するのは時間の無駄だから、そんな暇があったらコードを書け。MVの*の部分なんて"Whatever"でいいんだ。

※参考:AngularJSのMVWパターンを理解する - Qiita

WhateverのWなのねw

EJSをテンプレートに使う!

ところでExpress自体にはLaravelやRailsのようにHTMLのテンプレートを作る機能はないのだろうか?

APIを返すだけで React、Vue、AngularなどのJSフレームワークを使わないとExpress単体ではWebアプリは作れないのだろうか?

調べるとHTML部分はEJSやPugなどのテンプレートエンジンを使えばいいようだ!インストールするときにオプションとして選択するらしい。

※参考:Expressにおけるejsの使い方 - Qiita

つまりExpressの思想はコアな部分は必要最低限のみ用意するだけ。あとは必要に応じて自由に機能を追加して組み合わせればいいということみたい!

だからテンプレートエンジンで済ませたりVue、React、Angularなどのフレームワークと組み合わせたりいろんな選択肢があるということね。

Express以外のNodeフレームワーク

なお、Node.jsのフレームワークはExpress以外にもいろいろあるようだ。

Koa
Expressと同等のシンプルな設計のもと、ミドルウェアにES6流の非同期処理を追加したフレームワーク

Hapi
Expressと同等のシンプルな設計のもと、コードを設定ファイルのように記述できるフレームワーク

Sails
RailsライクでフルスタックなWebアプリケーションフレームワーク

Meteor
SPA向けの、フルスタックなWebアプリケーションフレームワーク

※参考:メジャーなNode用Webアプリケーションフレームワークを比較する - Qiita

この中ではExpress、Meteor、Sailsが三大フレームワークという位置づけのようだ。

※参考:【Node.js入門】3大フレームワーク「Express」「Meteor」「Sails」の特徴とは? | 侍エンジニア塾ブログ(Samurai Blog) - プログラミング入門者向けサイト

フルスタックフレームワーク「Meteor」ってちょっと気になるのだが、最近はあまり更新されてないっぽい。

※参考:Meteorのブームが来るか来ないと言われれば、来ないと思ってしまった件 – MMiyauchi Blog

やはり広範囲なフルスタックな技術を最新に保つのは結構ハードな作業な気がする。小さい機能を組み合わせる方が時代の風潮か。

最後に

ということでExpressとNuxt.jsの違いもわかってない状況からだいぶイメージが湧いてきました。同じような方がいれば少しでも助けになると嬉しいです。

この雲を掴むような「わからなさ」っててやはりネットワークやサーバサイド、バックエンドに対する圧倒的な知識不足から来ていると思っています。*1

Expressを入り口に実際に触ってREST APIでJSONを返す体験をしてみたいと思います! 凝ったバックエンドの開発はできないまでもどこまでのことができるのか?シリーズ化していきます。それではまた!


Expressを習得するためにやったことまとめ
qiita.com

*1:以前トライしたLaravelを今中断してるのも同様です。。