フロントエンド側+バックエンド側? React Next.js

パクリ32発目!!
寒くなってきて外に出なくなったらもっと進むのだろうか

パクリ元

内容

React 周辺を調査しているとよく出てくるのが Next.js という単語。幾分新しめの話らしいのであまりこなれていない気がする。パクリ学習はタイパ、コスパが大事なのでそこが若干気になるところ。

環境作成

パクリ元1つ目のページを参考に Next.js のセットアップ。とりあえず node インストールまでは 前回 React の場合と同じ。

~$ npm install -g yarn
・・・
~$ yarn create next-app --example with-typescript random-cat
・・・
~$ cd random-cat
・・・
~/random-cat$ yarn dev
・・・

SSR

Reactはクライアントサイドでのレンダリングに特化していますが、Next.jsはサーバーサイドレンダリング(server-side rendering; SSR)をサポートしています。これにより、初回読み込みの速度を向上させることができ、SEOやパフォーマンスにもよい影響を与えます。

SSRはウェブアプリケーションのレンダリングをサーバーサイドで行う技術のことです。通常、クライアントサイドレンダリング(client-side rendering; CSR)では、ブラウザがHTML、CSS、JavaScriptファイルをダウンロードして、JavaScriptを使用してページをレンダリングします。これに対して、SSRではサーバーがHTMLを生成し、ブラウザに送信します。

さぱーり仕組みが分かりません。

getServerSidePropsは、ページがリクエストされるたびにサーバーサイドで実行され、ページのプロパティを返す関数です。この関数を使用すると、リクエストごとにページのデータを取得できます。また、クライアントサイドでルーティングが発生した場合も、この関数がサーバーサイドで実行されます。

ふむふむ、なるほど。いやさっぱり理解できない。現代の人たちはこれだけで理解できるのか、さすがZ世代。ソースを見てもなぜサーバー側で動くのかが分からない。。

一応確認として、サーバー側で動かない場合の localhost アクセス時のソースは以下。

http://localhost:3000/
<!DOCTYPE html>
<html>
    <head>
        <style data-next-hide-fouc="true">
            body {
                display: none
            }
        </style>
        <noscript data-next-hide-fouc="true">
            <style>
                body {
                    display: block
                }
            </style>
        </noscript>
        <meta charSet="utf-8" data-next-head=""/>
        <meta name="viewport" content="width=device-width" data-next-head=""/>
        <noscript data-n-css=""></noscript>
        <script defer="" nomodule="" src="/_next/static/chunks/polyfills.js"></script>
        <script src="/_next/static/chunks/webpack.js" defer=""></script>
        <script src="/_next/static/chunks/main.js" defer=""></script>
        <script src="/_next/static/chunks/pages/_app.js" defer=""></script>
        <script src="/_next/static/chunks/pages/index.js" defer=""></script>
        <script src="/_next/static/development/_buildManifest.js" defer=""></script>
        <script src="/_next/static/development/_ssgManifest.js" defer=""></script>
        <noscript id="__next_css__DO_NOT_USE__"></noscript>
    </head>
    <body>
        <div id="__next">
            <div>
                <button>他のにゃんこも見る</button>
                <div></div>
            </div>
        </div>
        <script src="/_next/static/chunks/react-refresh.js"></script>
        <script id="__NEXT_DATA__" type="application/json">
            {
                "props": {
                    "pageProps": {
                    }
                },
                "page": "/",
                "query": {
                },
                "buildId": "development",
                "nextExport": true,
                "autoExport": true,
                "isFallback": false,
                "scriptLoader": [
                ]
            }</script>
    </body>
</html>

他のにゃんこも見る の下の div ブロックには何もない。一方、サーバー側で動くソースでアクセスした場合のソースが以下。

http://localhost:3000
<!DOCTYPE html>
<html>
    <head>
        <style data-next-hide-fouc="true">
            body {
                display: none
            }
        </style>
        <noscript data-next-hide-fouc="true">
            <style>
                body {
                    display: block
                }
            </style>
        </noscript>
        <meta charSet="utf-8" data-next-head=""/>
        <meta name="viewport" content="width=device-width" data-next-head=""/>
        <noscript data-n-css=""></noscript>
        <script defer="" nomodule="" src="/_next/static/chunks/polyfills.js"></script>
        <script src="/_next/static/chunks/webpack.js" defer=""></script>
        <script src="/_next/static/chunks/main.js" defer=""></script>
        <script src="/_next/static/chunks/pages/_app.js" defer=""></script>
        <script src="/_next/static/chunks/pages/index.js" defer=""></script>
        <script src="/_next/static/development/_buildManifest.js" defer=""></script>
        <script src="/_next/static/development/_ssgManifest.js" defer=""></script>
        <noscript id="__next_css__DO_NOT_USE__"></noscript>
    </head>
    <body>
        <div id="__next">
            <div>
                <button>他のにゃんこも見る</button>
                <div>
                    <img src="https://cdn2.thecatapi.com/images/abe.jpg"/>
                </div>
            </div>
        </div>
        <script src="/_next/static/chunks/react-refresh.js"></script>
        <script id="__NEXT_DATA__" type="application/json">
            {
                "props": {
                    "pageProps": {
                        "initialImageUrl": "https://cdn2.thecatapi.com/images/abe.jpg"
                    },
                    "__N_SSP": true
                },
                "page": "/",
                "query": {
                },
                "buildId": "development",
                "isFallback": false,
                "gssp": true,
                "scriptLoader": [
                ]
            }</script>
    </body>
</html>

img タグが入ってるんですねー。でも React てブラウザで動いてるんだよなー Next.js だからそういうもんだと思えばいいのかもしれんけど。

getServerSideProps理解

そこでパクリ元2つ目を見ると、、あまり理解できないというか、、タイミングがよく分からないが、server.js を立ち上げる時というかソース更新した時(?)、各ページの getServerSideProps に対応した JSON エンドポイントを作り出し、各ページが呼ばれたタイミングでその JSON エンドポイントを呼び出し、サーバー側で getServerSideProps を実行して取得したレスポンスをページの Props として渡して JSX を先に生成してしまう、と。さらにクライアントとサーバで実行環境が異なると違う結果になるかもしれないので、webpack で環境をまとめてそれをサーバーから配信すると。実行環境にてソース解析して動的にいろいろ作り出す、というわけだ。ふむふむ、分かったつもりにはなったがまあ難しいことをしていらっしゃる。以前サーバー側でのスクリプト(でなくてもいいけど)でのページ生成から SPAによる onload からのページ生成に移り変わっていったときの対応になるんでしょうかね。

とりあえず以前気になった、「Next.jsとViteどちらを選ぶべきか?」についてはやはり筋が違ってると理解。

雑感

機能(ページ)がたくさんある、レイアウトを書き直さないといけないアプリとかだと必要なんだと思うがとりあえず今の私には too much かな、ということでここで一旦 Next.js はやめることにする。