[Next.js]私たちのサイトに翼を差し込む(1)



ロゴから好きな次はjsについて知りましょう!

*サーバ側のレンダリング?(SSR)


サーバ側レンダリングとは、サーバ側でレスポンスコードを実行してレンダリングすることです.
では、なぜサーバ側レンダリングが必要なのでしょうか.
  • 検索エンジンの最適化を支援する(SEO).
  • トップページをすばやくレンダリング
  • 最近は周りに起業家がたくさんいます
    もしそうなら、各社が生き残るためには、ユーザーの前に十分に露出しなければならない.
    Google以外の検索エンジンではJavaScriptは実行されないため、クライアントレンダリングのみを行うサイトはコンテンツのないサイトと同じ扱いになります
    =>GoogleもSSRサイトのスコアを高くしています.
    では次はjsを使用する前に、直接的なサーバ側レンダリング環境を構築します.

    #サーバ・エンド・レンダー・プリミティブ

  • 反応器で提供されるrenderToString、水和物関数を使用します.
  • サーバが生成したデータをクライアントに転送する方法を理解する.
  • styled-conntを使用して作成されたスタイルが、サーバ側でレンダリングされるときにどのように処理されるかを理解します.
  • サーババンドルファイルの作成方法について
  • mkdir test-ssr
    cd test-ssr
    npm init -y
    npm install react react-dom
    npm install @babel/core @babel/preset-env @babel/preset-react
    npm install webpack webpack-cli babel-loader clean-webpack-plugin html-webpack-plugin

    1.クライアントでのみレンダリング



    プロジェクトルートディレクトリにsrcフォルダを作成し、その下にホームを作成します.js, About.jsファイルを作成します.
    各ファイルは、Webサイトのページを表し、ページ切り替えをテストします.
    // Home.js
    import React from "react";
    
    export default function Home() {
     return (
       <div>
         <h3>This is home page</h3>
       </div>
     );
    }
    
    // About.js
    import React from "react";
    
    export default function Ablut() {
     return (
       <div>
         <h3>This is about page</h3>
       </div>
     );
    }
    この家.jsとAbout.jsをレンダリングするAppコンポーネントを作成します.
    アプリケーションコンポーネントは、ボタンを介して各ページに移動する機能を提供します.
    import React, { useState, useEffect } from "react";
    import Home from "./Home";
    import About from "./About";
    
    export default function App({ page }) {
     const [page, setPage] = useState(page);
    
     useEffect(() => {
       window.onpopstate = (e) => {
         setPage(e.state);
       };
     }, []);
    
     function onChangePage(e) {
       const newPage = e.target.dataset.page;
       window.history.pushState(newPage, "", `/${newPage}`);
       setPage(newPage);
     }
     const PageComponent = page === "home" ? Home : About;
    
     return (
       <div className="container">
         <button data-page="home" onClick={onChangePage}>
           Home
         </button>
         <button data-page="about" onClick={onChangePage}>
           About
         </button>
         <PageComponent />
       </div>
     );
    }
    
    onpopstateって何ですか?
    * onpopstate(MDN)

    つまり、popstateでサーバ側でレンダリングすると、2つのページ間でstateをコピーできるので、state管理が可能になります!
    srcフォルダの下にあるindex.jsファイルを作成し、前に作成したAppコンポーネントをレンダリングします.
    import React from "react";
    import ReactDom from "react-dom";
    import App from "./App";
    
    ReactDom.render(<App page="home" />, document.getElementById("root"));
    
    今からパッケージを設定しましょう!(WebPackが一番難しいと思います)
    プロジェクトルートディレクトリでwebpackを使用します.config.jsファイルを作成し、次のコードを入力します.
    const path = require("path");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    
    module.exports = {
      entry: "./src/index.js",
      output: {
        filename: "[name].[chunkhash].js",
        path: path.resolve(__dirname, "dist"),
      },
      module: {
        rules: [
          {
            test: /\.js$/,
            use: "babel-loader",
          },
        ],
      },
      plugins: [
        new HtmlWebpackPlugin({
          template: "./template/index.html",
        }),
      ],
      mode: "production",
    };
    
    templateフォルダを作成し、その下にindexを作成します.htmlファイルを作成します.
    <!DOCTYPE html>
    <html>
      <head>
        <title>test-ssr</title>
      </head>
      <body>
        <div id="root" />
      </body>
    </html>
    バーベルをセットする
    バーベル設定ファイルを作成してJavaScriptファイルをコンパイルします.
    ルートにbabelnofigがありますjsファイルの作成
    const presets = ["@babel/preset-react", "@babel/preset-env"];
    const plugins = [];
    module.exports = { presets, plugins };
    babel.config.jsファイルの設定はbabel-loader実行時に適用されます.
    クライアントの表示を確認します!!

    Webspecを実行します.npx webpack
    これはだめです.


    これでいいです.
    urlはfile://で始まるため、push Stateメソッドを呼び出すとエラーが発生します.これは、サーバを直接移動することで解決できます.
    もちろん、最初のリクエストに対する応答として返されるHTMLには、ボタンや文を表すドーム要素はありません.ボタンまたは文のドーム要素は、JavaScriptを実行するときに追加されます.ブラウザオプションでJavaScriptの実行が許可されていない場合は、画面に何も表示されません.

    2.サーバー側レンダリング関数の使用を試みる


    4つのサーバ・エンド・プレゼンテーション関数
  • renderToString:静的ページのレンダリング用
  • renderToNodeStream:上動
  • renderToStaticMarkup:初回レンダリング後も状態変化に応じて画面を更新し続ける場合
  • renderToStaticNodeStream:上動
  • まず、レンダリングサーバ側に必要なパッケージをインストールします.npm install express @babel/cli @babel/plugin-transform-modules-commonjsexpressパッケージをインストールしてWebサーバを解放します.@babel/cliパッケージをインストールして、サーバが使用するJavaScriptファイルをコンパイルします.
    =>サーバもJSX構文作成のJavaScriptを実行する必要があります.
    ESMで作成したモジュールシステムをcommonJSに変更するために、後ろにパッケージをインストールしました.
    Webサーバコードを記述するには、次の手順に従います.
    srcフォルダの下にあるサーバ.jsファイルを作成し、次のコードを入力します.
    import express from 'express';
    import fs from 'fs';
    import path from 'path';
    import { renderToString } from 'react-dom/server';
    import React from 'react';
    import App from './App';
    
    const app = express();
    const html = fs.readFileSync(
      path.resolve(__dirname, '../dist/index.html'),
      'utf8'
    );
    app.use('/dist', express.static('dist'));
    app.get('/favicon.ico', (req, res) => res.sendStatus(204));
    app.get('*', (req, res) => {
      const renderString = renderToString(<App page='home' />);
      const result = html.replace(
        '<div id="root"></div>',
        `<div id="root">${renderString}</div>`
      );
      res.send(result);
    });
    
    app.listen(3000);
    本を読みながら書くだけで、知らないところが多いです.片付けよう
  • react-domパッケージのサーバフォルダの下にサーバが使用する機能が集約されている.
  • expressオブジェクトapp変数を使用して、ミドルウェアとurlパス設定を行うことができます.
  • renderToString関数を使用してApp構成部品をレンダリングします.renderToString関数は文字列を返します.
  • バーベルをセットする
    サーバとクライアントに必要なバーベルプラグインとプリセットは次のとおりです.
  • クライアント
  • パウエルプリセット:@babel/プリセット-react,@babel/プリセット-env
  • バーベルカード:なし
  • サーバ
  • パウエルプリセット:@babel/プリセット-react
  • バーベルカード:@babel/plugin-transform-modules-comonijs
  • プロジェクトのルートディレクトリにbablerc.common.js, .babelrc.server.js, .babelrc.client.jsファイルを作成し、次のコードを入力します.
    // .babelrc.common.js
    const presets = ['@babel/preset-react'];
    const plugins = [];
    module.exports = { presets, plugins };
    
    // .babelrc.client.js
    const config = require('./.babelrc.common.js');
    config.presets.push('@babel/preset-env');
    module.exports = config;
    
    // .babelrc.server.js
    const config = require('./.babelrc.common.js');
    config.plugins.push('@babel/plugin-transform-modules-commonjs');
    module.exports = config;
    
    一般的な設定は次のとおりです.babel.common.jsによって管理され、クライアント側とサーバ側がこれらの設定をインポートし、使用します.
    Webパッケージの設定
    Webパッケージ設定ファイルでは、HTMLに追加されたバンドルファイルのパスとバーベル設定ファイルのパスを変更する必要があります.

    パブリックパスとオプションが追加されました.
  • publicPath html-webpack-pluginがHTML生成時にHTML内部リソースファイルを作成するためのパスを設定します.publicPath設定なしで生成されたHTMLファイルは、ブラウザですぐに実行しても問題はありませんが、サーバ側でレンダリングすると問題が発生します.
  • その他の設定とプログラムの実行
    サーバ側コード@babel/cliを使用してバーベルのみを実行し、クライアントコードはWebパッケージを実行します.package.jsonを修正します.
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "build-server": "babel src --out-dir dist-server --config-file ./.babelrc.server.js",
        "build": "npm run build-server && webpack",
        "start": "node dist-server/server.js"
      },
    サーバ側レンダリングではドーム要素が作成されているので、クライアントが再レンダリングする必要はありません.ただし、各ドーム要素に必要なイベント処理関数を接続する必要があります.イベント処理関数が接続されていない場合、画面ははっきり表示されますが、ユーザーがボタンを押しても反応しません.
    リアクターが提供する水和物関数は、サーバ側のレンダリング結果によって生成されたドーム要素に必要なイベント処理関数を追加します.
    index.jsファイルに追加するには、水和物関数を使用します.
    ReactDom.hydrate(<App page='home' />, document.getElementById('root'));
    次に、次の操作を行います.npm run build npm start

    また、ブラウザからローカルホスト3000に接続することで、画面が正しくレンダリングされ、ページを切り替えるボタンが正常に動作することがわかります.
    内容は少し長いですが、サーバーデータがクライアントに転送された部分から、次のブログに書くつもりです.