質問: Next.jsやGatsbyのSSGに関する私の認識が合っているかどうか、お伺いしたいです。 SSGすると静的サイトが出力できる、という話をあちらこちらで耳にします。 それで私は、SSGではReactを含まないピュアなHTMLが出力されるのだと思っていたのですが、最近これは間違っているのではないかと思うようになりました。 実際には 1ビルド時には通常のReactアプリケーションと、初期表示用のレンダリング済みHTMLが出力されている。 通常のReactアプリケーションなので、ボタンクリックなどを契機として副作用を起こしてやればクライアントサイドレンダリングが行われて画面が更新される。 2ルーターによる画面遷移時には次画面のjsとビルド時に取得されたデータがダウンロードされ、クライアントサイドレンダリングが行われる。 次画面の初期表示用のHTMLは、ルーターによる遷移では使用されない。 ということなのではないかと思うのですが... 合ってますでしょうか。 よろしくお願いします。
回答: > > それで私は、SSGではReactを含まないピュアなHTMLが出力されるのだと思っていたのですが、 > > > Reactを含む含まないという話ではなく、生成されたHTML中にどういったscriptタグが埋め込まれているのか着目したほうがよいと思います。読み込まれるJavaScriptによってページの動的な振る舞いが制御されるため、まずは何が読み込まれているのかをしっかりと確認してみてください。ここで初めてReactうんぬん、という話が発生します。 `実際には〜`以降の解説を後述していますが、基本的にはscriptタグに埋め込まれたJavaScriptの仕事の範疇であって、質問中で気にかけている部分とは別の文脈であることを理解してください。 > > 1ビルド時には通常のReactアプリケーションと、初期表示用のレンダリング済みHTMLが出力されている。 > > > はい。SSG(Static Site Generate)によってHTMLをexportしています。この際出力されるHTMLは表示内容が明らかに決まっている場合は表示するコンテンツを埋め込み、そうでない場合(動的に変更したい場合)はスケルトン(UIのプレースホルダー)や、明らかに決まった初期値(サイトのロゴなど)を埋め込むのが理想的です。 eventのバインドや、クライアントサイドでの動的な更新(CSR = Client Side Rendering)を実現するためには、`ReactDOM.render`か`ReactDOM.hydrate`のAPIを利用してDOMをReactの管理下置きます。 * * > > 2ルーターによる画面遷移時には次画面のjsとビルド時に取得されたデータがダウンロードされ、クライアントサイドレンダリングが行われる。 > > > はい。あっています。nextjsのrouterやreact-router-domなどを利用してページ遷移を実装している場合、History APIによってURLが制御されています。 なぜ制御しているかというと、クライアントで直接URLをかきかえることでページリロード時のように新しくリソース(js/cssなど)を取得する必要がなくなるからです。URLの変更eventを各ページのRouterのContextが検知して、それぞれの初期化が走り、差分があるとreactが更新してくれる、という感じです。挙動自体はCSRと同じですね。 ただこれらの実装をやろうとするとけっこう大変なのでnextjsやreact-routerを利用して隠蔽しているといった状況です。 > > 次画面の初期表示用のHTMLは、ルーターによる遷移では使用されない。 > > > ご推察のとおりだと思います。ただし、nextjsやreact-routerなどが提供しているLink系のコンポーネントを利用 しないとRouterのContext内でHistoryの管理ができなくなるため、ただのリンクとして扱われ、CSR的な振る舞いではなく新しくHTMLを取得して初期化が行われます。 参考 nextjsだとこのあたりでHistory APIをwrapしています。 * *