見出し画像

React部分導入時の開発・検証環境紹介

画像1

この記事は食べログアドベントカレンダー2020の1日目の記事です。
2020年も残り1ヶ月になりました。早いものですね。

この記事を執筆するのは、食べログでフロントエンドチームに所属する@hagevvashiです。

はじめに

食べログではRuby on Rails(以下RoR)を用いており、サイトの大部分がRoRによってHTMLのレンダリングまで行われています。JavaScriptでの実装はほとんどがjQueryなどを用いた非宣言的なものとなっています。

歴史あるサービスなので、それなりにコード量が増えかつ複雑になっています。例えば既存のjQueryやBackbone.jsで書かれたソースコードを変更するのに予想外のコストを強いられたりします。

食べログを引き続きユーザにとって価値のあるサービスにするためには、いち早く新しい機能を届ける必要があります。そして、そういった予想外のコストを少しでも減らすために食べログのエンジニアがいます。我々フロントエンドチームはReactを使った宣言的なフロントエンド実装を始めました。この辺りの話は過去にもしているので興味があれば是非ご覧ください。

この記事について

世の中にはシングルページアプリケーション(以下SPA)やスタティックサイトジェネレーション(SSG)での開発についてのノウハウが溢れています。WebAssemblyの動向もあるにせよ、フロントエンドのツールチェーンはNode.jsに集約されました(※1)。今後もJavaScript、TypeScriptでのWebサービスの実装が当たり前の時代は続くでしょう。

しかしながら世の中のほとんどのサービスが上述の環境で作られているわけではありません。広く認知されていて歴史の長いサービスほど、マルチページアプリケーション(以下MPA)環境で作られていることが多いと思います(※2)。マルチページアプリケーションとは、RoRに限らず、Laravel、Django、Springなどのwebフレームワークでサーバサイドルーティングとサーバサイドレンダリング(以下SSR)を行っているアプリケーションを指しています。

いち早く新機能をユーザに届けるためにも、React等のフレームワークを利用した宣言的なフロントエンド実装にしていきたいと考えると思います。しかしながら、歴史あるサービスは様々な機能が実装され、1ページに載っている機能をまるごと置き換えてのリリースは難しい時もあります。そういった状況では部分的にReactを導入するという選択を取らざるを得ない方々もいると思います。

この記事は、所謂MPAで作られているwebサービスに部分的にReactを導入し始めている、これから導入しようとしている方に向けて検証環境に関するノウハウをお届けするものです。

※1. Front-End Study #1「Cloud Native時代のフロントエンド」 - connpass 基調講演より
https://speakerdeck.com/mizchi/hurontoendoling-yu-wozai-ding-yi-suru?slide=6
※2. stackoverflow’s developer survey 2020 より

解決したい課題

以降RoRなどのwebフレームワークによって実装されているMPA環境のことをRoRと表現します。必ずしもRoRを用いている方に向けた文章ではないのでその点ご留意くださいませ。

RoRにReactを部分導入する場合、いくつか困る点があると思います。

・フロントエンドビルド環境が古い、無い
・既存のフロントエンドプロジェクトと別に管理したい
・RoRと独立して開発したい

などなど

React用の別プロジェクトを作る

これらの問題に対しての解決策は新規プロジェクトでReactプロジェクトを用いることです。既存のビルドシステムと切り離した別のシステムを作成し、RoRの各アクション毎にbundle.jsを生成するようなビルド設定にしてください。

jQueryなどのライブラリとReactを統合する形での導入の方法も公式ドキュメントにて紹介されていますが、その方法はとりません。

そもそも何故「既存のフロントエンドプロジェクトと別に管理したい」や「RoRと独立して開発したい」という問題が出てくるのでしょう。それはReactとRoRを完全に切り離すことでシステム境界を設けることができるからです。Reactのプロジェクトを切り離して作ることによって、サーバサイドの事情やjQueryなどの非宣言的なJavaScript実装を考慮に入れず独立した開発が行えるようになります。

もちろんRoRがブラウザにレスポンスするHTML上において、Reactのプロジェクトのbundle.js(manifest.json)は既存の資源とともに存在することになります。そのため、webpackなどのバンドルツールの最適化の恩恵を享受することができなかったり、polyfillの重複などのパフォーマンス上の問題はあるかもしれません。ですので、この点はフロントエンドアーキテクチャを考える方々と議論して結論を出しましょう。

以降はReact用に別プロジェクトを用意した前提の話になります。

まずはReactを導入した後の検証環境について整理しましょう。

sandbox検証環境

sandbox検証環境とは、コンポーネントを単体で動作させ検証できる環境を指しています。storybookなどのツールが有名ですね。

Storybook上ではダミーデータの挿入やapiのmockを行うことが可能です。

Storybookなどのsandbox検証環境でコンポーネント個々の検証は十分に可能です。

MPA組み込み環境

複数のUIコンポーネントが複合的に動作する環境として、productionとほぼ同等の環境も必要です。

Reactを部分導入している以上、Reactでページ全体を構成しているわけではありません。部分導入している世界では、RoRによってブラウザにレスポンスされたHTMLの一部分に対して、Reactコンポーネントがマウントされる・・・という状態になります。

RoRがURLルーティングを行っているということは、静的なルーティングにより導出されるパラメータを何らかの形でReactコンポーネントに引き継ぐ必要があります。また、URLルーティングをRoRが担っている以上は、リクエストのクエリパラメータをJSにより取得することは避けたいです。Reactコンポーネントは、静的ルーティング+クエリパラメータを結合させた状態を受け取る必要があります。そういった所謂初期データは、一般的にはRoRによってSSRされたHTML上にjsonデータとして埋め込まれたりすることが多いと思います。

ここではクエリパラメータではありませんが、HTML上にjsonデータを埋め込むという部分に焦点を当てた例を紹介します。HTML上に埋め込む場合は2つ方法があります。

・カスタムデータ属性にjsonデータをシリアライズして埋め込む
・scriptのtype属性を"application/json"に指定し、script内部にjsonデータを埋め込む

例: カスタムデータ属性を用いる場合(上のjsonデータを下のhtmlのようにする必要があります)(※3)

また、サイト規模が大きく閲覧数の多いサイトでは大きなリリースがしにくいので、コンポーネント同士のデータのやり取りがしづらい粒度でのリリースを求められるケースがあります。結果として、例えば、既存のformからユーザの入力状態をJSで取得し、コンポーネントに引き継ぐという状況が考えられます。FormDataなどのAPIを用いることで実現は可能です。

そのような状況で確実に検証ができる環境はRoRに組み込んだ状態です。

※3. 下記のようにscriptタグのtype属性を"application/json"とすることで無駄なエスケープを避けることができます。ただ、reactから参照する要素がマウントする要素とjsonが格納されたscriptタグの2つになってしまいます。こういうことを求めるコンポーネントが2つ3つになってくるとDOMアクセスが面倒なので1つの要素にまとめた方が楽です。

sandbox環境とMPA組み込み環境の問題点

■sandbox環境はあくまでsandbox環境

sandbox環境はあくまでUIコンポーネントのsandbox環境です。アプリケーションとしてのコンポーネントツリーの確認には不向きです。

アプリケーションとして確認したいことはコンポーネント間の連携です。部分導入ではReact.portalを用いたコンポーネントも頻出します。

また、storybookではproductのビルド設定での確認ができないため、その点も考慮に入れましょう。storybookは独自のビルド設定を持っているため、storybook上で確認できるコンポーネントの状態とプロダクションで確認できるコンポーネントの状態が異なる可能性があります。

■MPA組み込み環境は大変

React用に別プロジェクトを用意したのは何故でしょう?

それはReactとRoRを完全に切り離しシステム境界を設けることで、サーバサイドの事情やjQueryなどの非宣言的なJavaScript実装を考慮に入れず独立した開発が行えるからです。

せっかく独立した開発が行えるにもかかわらず、RoRへの依存の大きい開発は苦痛が伴います。

・RoRのエラーが出ていたりする
・RoRが重い
・サーバサイドでjsonデータ構築の実装完了を待たないと確認ができないため、ダミーデータのコミットが必要
・サーバサイドの変更のブランチにReactのマウント先要素のコミットや、JSファイル読み込みのコミットが必要

また場合によっては以下のような問題もあるかもしれません。

・リポジトリが大きい
・VMに入るのが面倒
・docker環境のセットアップが面倒

総じて環境を用意するのが手間独立していないということに尽きると思います。

コンポーネント結合環境

sandbox環境とRoRに組み込んだMPA組み込み環境に加え、RoRに依存せず複数コンポーネントの挙動を確認できる環境が欲しくなります。

部分的に導入していくAction毎に、静的なHTMLファイルを用意したらどうでしょう。そのHTMLファイルはRoRがレスポンスするHTMLをシミュレートしたものです。これがコンポーネント結合環境です。

静的なHTMLを用意することによって、Reactのプロジェクトに閉じた状態でコンポーネントの結合した動作の確認ができるようになります。RoRのことについては一切気を配る必要がありません。したがって「Reactで動くアプリケーションの確認が大変」という問題は無事に解決できました。

SPAではindex.htmlからbundle.js(manifest.json)をよびだすだけでアプリケーションが成立します。そのため、プロダクション環境がそのまま検証環境となります。

Reactの部分導入とはいえ、目指す状態は上述のSPA構成(※4)ですよね。SPA構成では、ブラウザからのリクエストに対して最初に返すべきHTMLをフロントエンドのプロジェクトが管理する状態になっています。最初に返すべきHTMLには下記内容が含まれています。

・適切にcode-splittingされたJSファイルの読み込み
・マウントする要素

早い段階でHTMLをプロジェクトに組み込んでくことによって、Reactの導入プロジェクトの進捗状況の目安になるかもしれません。「最終的にそのHTMLがデプロイ対象になるんだ」というゴールに向かって行く様子が伺えますね。

※4. ここではクライアントサイドでのルーティングという観点ではなく、ページのほぼ全てのHTML構造をJavaScriptによってレンダリングするという特徴を重視しています。

新たな問題

やってみるとすぐに分かることがあります。静的なHTMLの用意というのはそう簡単にはいかないのです。次のような問題にすぐに直面することになるでしょう。

・HTML上にjsonを埋め込む時にテンプレートエンジンを使いたくなる
  ・カスタムデータ属性に挿入する時
  ・ダミーデータをjsonファイルで作っている時
・リストデータを定義してリストタグをイテレーションで作りたい
・templateにして変わる部分だけを書きたい

静的にHTMLを作らなければならない辛さそのままですね。

この問題を解決するには動的にHTMLを生成すればよいのですが、その方法を2通り思いつき実際に試してみました。以降では2通りそれぞれの方針、実装方法、メリットデメリットについて紹介します。

解決策2つの方針

まずは2通り解決策の方針を示します。

■方針1: Node.jsでサーバを実装する
■方針2: html-webpack-plugintemplate機能を用いる

あくまで検証用の環境ですので、生成するHTMLもダミーのデータが入力されているもので十分です。リクエストパラメータの反映などはする必要ありません。そこまでしたら検証用環境としてはtoo muchです。

またこのために新たなライブラリを多数追加するのもtoo muchですので(※5)、追加しても1つのライブラリくらいにしたいです。極力プロジェクトに新たなライブラリを追加することなく、コストを少なく実現する方法として思いついたものは上記の2通りでした。

「Node.jsでサーバを実装する」という意味はそのままですね。新たにサーバフレームワークを使うこと無く、コアなAPIのみでサーバを実装しましょうというものです。ただしファイルの変更監視と反映に関しては重い実装になりそうなので、変更監視用のライブラリは用いることにします。

html-webpack-pluginについてはSPAでプロジェクトを作成する時によく(?)見かけるライブラリですね。あらかじめ用意したテンプレートHTMLに、webpackの設定に応じてJSの読み込みを追加してHTMLを生成するというwebpackのプラグインです。様々なオプションがあり、例えば、scriptタグの挿入位置をheadにするか、bodyにするか、あるいは挿入しないか・・・のような指定ができます。

そして2つの方針両者に共通する点があります。templateにreactを使い、予め何かしらstyleを適用しておきたい場合にstyled-componentsを利用する、という点です。

これはReactのプロジェクトなので下記のような欲求を満たすことになります。

・書き慣れたjsxでテンプレート管理したい
・書きなれたstyled-componentsでstyleを管理したい
・もし実際のプロダクトで利用しているコンポーネントと同じものがあれば使いまわしたい

それではそれぞれの詳しい実装方法について紹介していきます。

※5. とは言え追加するライブラリが多数のライブラリを使用している場合もあるので厳密なものではありません

方針1: Node.jsでサーバを実装する

この方法は、RoRがリクエストパラメータに応じてデータベースなどからデータを取得し、ユーザが求める情報をHTMLに埋め込んでブラウザに返却する、という流れを非常に簡素化したものになります。

■シンプルな実装からスタート

まずは一番シンプルなサーバの実装からしてみます。

Node.jsのhttpモジュールを用いるだけです。起動時に `-p 4000` のような形でオプションを受け取れるようにします。

TypeScriptで実装しています。requestオブジェクトとresponseオブジェクトは型をつけるのが難しくてanyにしてしまいました。

■html構造をテンプレート化し、外からtitle,style,script,マウント要素などのhtml要素を渡せるようにする

<!doctype html><html>〜</html>の部分はタイトルや読み込むscript、style、用意する前提要素などを外から入れられるように関数化してしまいましょう。

■styleとhtml要素をreactとstyled-componentsで作成

外からstyleタグやhtml要素を渡すことが可能になったため、jsxとstyled-componentsを使って作っていきます。

■MPAなのでURLルーティングをする

RoRの各アクションをシミュレートとしたHTMLを用意するという話なのでさらにルーティングを実装します。上記のjsxを用いた実装はほぼ全て関数化し、ルーティングの結果呼ばれるものとします。

■APIがパスで切られている場合はreverse proxyの実装をしておく

OpenAPIやJSON Schemaを用いてAPI開発をしている場合、ドキュメントを元にstub serverを実行することが簡単にできます。

ドキュメントを用意するだけでstub serverをたててくれるようなOSSもあるので有効活用していきましょう。OpenAPIの場合は@stoplight/prism-cliなどです。

開発時はstub serverでコンポーネント実装を進めていきますが、現在用意している検証用の環境でも必要になります。

ただ、/apiだったらapiへのリクエストになるようなReverse Proxyの構成の場合、同様の構成を再現するためNode.jsで実装する必要があります。とは言えその実装はとても簡単です。

■コンテンツサーバの実装

例えばjestのカバレッジを./coverageに出力している場合などでは、コンテンツサーバの実装をしておくと便利だったりします。

※これはなくても問題ないと思います。

■ファイルの変更を監視して次からのリクエストに反映する

このままだと、実装したこのscriptを実行しても変更の検知はしてくれないためts-node-devというライブラリを使って解決します。

ts-node-dev --files --respawn scripts/server.tsx -p 8000

※もしTypeScriptのpathsを用いている場合は`-r tsconfig-paths/register`を引数に渡してあげましょう

■webpack-dev-serverのlive reload(+HMR)に対応させる

ここまででビルドしたファイルを読み込むだけでしたら十分機能する検証環境ができたのですが、webpack-dev-serverなどを用いた開発ではlive reloadやhot module replacement(HMR)の恩恵を受けたいところです。

後述のhtml-webpack-pluginを用いてdev-serverがHTMLを生成する場合は追加の設定をしなくても恩恵を受けられるのですが、今回のケースのようにHTMLが別口で用意される場合はwebpack-dev-server側でのreverse proxyの設定が必要です。当然RoR上でwebpack-dev-serverを起動するような場合にlive reloadやHMRをしたい場合には、reverse proxyの設定が必要です。

■まとめ

この程度のことだけであれば思ったより簡単に実装できました。reactとstyled-componentsのSSR用のAPIも想像以上に記述量が少なくて済みました。

そして一旦ここまでのscriptが用意できてしまえばあとはxxxActionの関数とrouteのcaseを増やしていけばページが増えても簡単にスケール可能です。

とはいえサーバの実装が必要なことは間違いないため、一切サーバの実装はしたくない場合はhtml-webpack-pluginを用いた方法がおすすめです。

方針2: html-webpack-pluginのtemplate機能を用いる

この方法ではhtml-webpack-pluginを用いてHTMLの生成を行います。

方法1との大きな違いは、HTMLのビルドをおこなうため各ページ分静的なHTMLを生成することができる点にあります。APIに関する何かしらの解決(※6)が前提にはなりますが、CIでartifactsにデプロイし確認ができたりします。

またwebpack-dev-serverでは、方法1のようにreverse-proxyの設定をしなくてもlive reloadやHMRの恩恵を受けることができます。

各ページ分のchunkとtemplateのひも付き設定が鍵になるため、その辺りから見ていきましょう。

※6. 例えば、ServiceWorkerなどでのAPI Requestのmockなど

■entryに動的にchunk指定をする

そもそもMPAに部分的にReactを入れていこうという話が前提になっております。ですのでこの辺りの設定はできていて当然なのですが、改めて見ていきましょう。

webpackのconfigのentryに、Record<string, unknown>のようなデータ型を渡すことでMPAに対応したchunk設定が可能になります。

具体的には下記のような指定の仕方でMPAの設定が実現できます。また、キーに対して配列を指定することで必ず読み込ませておきたいファイルを指定することもできます。polyfillなどの読み込みに使う場合もあるかもしれないですね。

ここではentry1やentry2がchunkの名前になります。

まずはこのデータを動的に作ることから始めてみましょう。動的に作るとはどういうことかご説明します。プロジェクトのディレクトリの構成からファイルを抽出し、chunkの設定を構成に依存させることができるということを動的に作ると定義しています。新しいページのエントリーファイルが追加になっても、設定ファイルを修正する必要がないのは便利ですよね。

ファイルの抽出にはglobというライブラリを用います。chunkの名前も動的に作られる必要があるため、文字列操作メソッドを利用してextensionなどを削ったりします。このようにして作られた配列データをObject.fromEntriesを用いて上記のようなデータ構造に変えてあげることで動的なentry設定を実現します。

これで動的なentryの設定ができました。

■chunkの設定をhtml-webpack-pluginとマッチさせる

html-webpack-pluginのオプションにchunksというパラメータがあります。

chunksに指定したchunk次第で、生成されるHTMLに挿入されるJSファイルの読み込みが決まります。chunksに何も設定しなかった場合は"all"扱いとなり全てのJSファイルの読み込みscriptタグが挿入されます。

filenameはhtmlが出力されるパス及びwebpack-dev-serverでアクセスするパスになります。

templateにjsxを指定することが可能なのですが、一旦適当に設定して、chunkの設定だけ済ませましょう。

■templateを実装する

templateに指定したファイルの実装をしていくのですが、これはNode.jsでサーバを実装したところの、templateHtmlやreactとstyled-componentsでstyleやHTML要素を作成する部分とほとんど同じになります。そのため、html-webpack-plugin独自の内容だけ紹介します。

templateの実装において肝心なのが、如何にtemplateとして共通のものを切り出すかという点です。今回html-webpack-pluginのtemplateフィールドに指定するtemplateのソースは1ファイルにしたいと思います。

ということはそのtemplateの内に、chunkに応じて生成するHTMLを動的に切り替える実装をする必要があるということになります。

templateの関数は、HtmlWebpackPlugin.TemplateParameter型の引数を受け取ります。

htmlWebpackPluginというフィールドのoptionsにはwebpack.config.tsでの設定が反映されています。ということはoptionsのchunksフィールドは動的に生成されているので、このフィールドの値を元に動的に返すHTMLを作ればよさそうです。その実装が下記です。

validateChunksという関数は、chunksの型が`"all"|string[]|undefined`で静的には使いづらいため、runtimeでエラーを返さない場合は[string]というtupleになるように保証するための関数です。

validateChunksを通過したchunksはstring型の要素が1つのtupleという安心感があるため、分割代入で要素を取り出すことが可能になります。

あとはルーティング用の関数に投げてchunkに応じたコンポーネントを返してもらうだけです。

■webpack-dev-serverの起動時の表示をなんとかしたい

この状態で既に使えるようになっているのですが、webpack-dev-serverを起動した際に表示される画面にやや問題があります。起動直後はプロジェクトルートのディレクトリ・ファイル一覧が表示された状態だからです。この原因はdevServer.contentBaseに何も指定していないためプロジェクトルートを指してしまっていることにあります。

entryのchunkの設定と必ずしも一致してある必然性はないのですから、/index.htmlというHTMLをhtml-webpack-pluginで作ってしまえばこの問題は解決できそうです。

推奨される方法かは分かりませんが、entryで設定したchunkに存在しない文字列をchunksに渡すことで、やりたいことが実現できます。

まずはwebpackの設定ファイル側を修正します。filenameを"./index.html"にし、chunksにありえない名前("index")を指定するだけです。templateは共有します。

templateを共有するためこのままだとroute内でswtichのdefaultに到達しErrorをthrowします。

chunkに指定した無意味な"index"という値はここまで突き抜けてくるためcaseに追加することで対応可能です。

■apiのreverse proxyの設定

Node.jsでサーバ実装する際は、apiのreverse proxyもNode.jsで実装しました。今回はサーバはwebpack-dev-serverになっているため、webpack-dev-serverのproxyの設定でreverse proxyの設定を行います。

■react-refresh/babelを呼ばない

fast refreshを用いたHMRを行っている場合、react-refresh/babelのplugin読み込みをスキップしなければなりません。ただし、html-webpack-pluginでreactのコンポーネントをtemplateとして使用していて、jsxの変換をプロダクトのbabelの設定と共有しているという場合のみです。

html-webpack-pluginのtemplateに指定したファイルの拡張子は.tsxです。

プロダクトコードの拡張子も.tsxのため、webpackのconfigのuseでbabel-loaderの対象も.tsxが引っかかるようにしています。

html-webpack-pluginの仕様上useで引っかかったらそのloaderを適用するため、特段新たな設定をしなくてもtsxをtemplateとして利用することが可能になります。

ただし、実は設定を共有してはいけない場合もあります。プロダクトのビルドとしてコンポーネントをbabelを通し変換するというbabel-loaderの使い道と、検証用のHTMLを用意するためにbabelを通し変換するという別のbabel-loaderの用途で共通の設定ファイルを利用しているからです。

ここでは実は共有してはいけない設定をスキップしましょう、という話をしていきます。

ちなみにもしスキップしなかった場合は下記のようなエラーが表示されます。

ReferenceError: $RefreshSig$ is not defined

babel.config.jsファイルでexportするコールバック関数の引数として渡されるapiオブジェクトのcallerメソッドを使用するとスキップ判定ができます。

callerメソッドにわたすコールバック関数の引数のcallerオブジェクトは、下記のようなデータ構造になっています。

手元の環境だと、targetフィールドには"web"か"node"が来るようでした。そしてtargetが"node"の時、html-webpack-pluginからbabel-loaderが呼び出されているということを示しているようです。

ということで、callerメソッドを用いて実装します。

■まとめ

これにてhtml-webpack-pluginでの設定が完了しました。

肝心のreactとstyled-componentsを用いてtemplateを実装していくという部分はNode.jsでサーバを実装していた時とほとんど同じものになっています。

fast refreshのところだけ若干トリッキーなことをしてしまいましたが、html-webpack-pluginだけでここまでできるとは思っていませんでした。

方法1と方法2の比較

方法2のhtml-webpack-pluginを使うパターンの方が優れているため、Node.jsでのサーバ実装をする必要はないでしょう。

ただし方法2の場合はwebpackの設定やloaderの設定が異なるだけでまったく想定外のエラーが出る可能性が十分にあります。完全にwebpackと切り離されているという意味で方法1の方がハマりどころは少ないです。

■方法2の方が優れている点

・方法2だと、code splittingに対応している(方法1で紹介した実装のみだとcode splittingに対応できない(※7))
・方法2の方が修正コード量が圧倒的に少ない
・方法2ではサーバの実装をせずに済む
・方法2ではprodution build時に静的HTMLを生成できるため、CIのArtifacts利用など、開発時のdev-server以外にも用途がある

※7. production buildにおいてということになるので、あまり機会はないかもしれないですが、prodcution build時にも使えるということを想定して作っています。とはいえ方法1の方にcode splittingに対応する実装を追加すればよいだけです

ただし、方法1の方が優れている点がいくつかあります。

・方法1の場合、webpackとは完全に切り離して実装することになるので、ここで紹介したwebpackの設定と異なっていても検証用のHTMLを返すサーバの実装には影響がない。(方法2の場合、webpackの設定の違いやloaderの設定の違いを受ける可能性が高い。ハマりやすい)
・方法1だと、production build時にもNode.jsのサーバによってHTMLを生成するため、reverse proxyのことを考えなくて済む(方法2の場合は、静的なHTML生成となるため、reverse proxyの設定をした簡易サーバをたてるか、Node.jsなどでサーバ実装をするか、service workerを用いたapi mockをする必要がある)
・方法1の場合、jsやcss、画像をCDN経由さているMPAのケースにおいて多少有利かもしれない。上記とほぼ同じ理由により、production build時には追加の実装をしなくても本番と似たような構成になる。(方法2で同じことを再現しようとすると多少悩む必要がある。)

まとめ

・歴史あるサービスはMPAでかつリリース制約があることが多く、React部分導入となることもある
・もとがSPA構成ではないので、部分導入箇所用の動作確認環境の準備が別途必要
・動作環境は個々のUIコンポーネント確認用のsandbox環境、既存のwebフレームワークとのつながりを確認するMPA組み込み環境、さらに静的HTMLをシミュレートしたコンポーネント結合環境の3つあるとよい
・静的HTMLをシミュレートした環境構築は、Node.jsでサーバを実装する方法と、html-webpack-pluginを用いる方法がある
・多くの点でhtml-webpack-pluginを用いる方法が優れている
・ただしいくつかの点でNode.jsでサーバを実装する方が楽な場面がある(特にwebpackの設定の影響を受けなくて済む点)

さいごに

食べログFEチームでは、一緒に楽しくリプレースに取り組んでくれる仲間を大募集中です!

・難しい課題にチーム一丸となって取り組みたい
・柔軟に働ける環境で自分のスキルを活かしたい
・React/TypeScriptでバリバリ開発したい
・レガシーなシステムのリファクタリングがしたい
・アーキテクチャについて探求したい
・食べログというプロダクトに貢献したい

どれかに当てはまった方は以下のリンクを是非御覧ください!

明日は食べログアドベントカレンダー2020の2日目の記事が公開されるのでご期待ください!

この記事が気に入ったらサポートをしてみませんか?