ゲーム開発
Unity
UnrealEngine
C++
Blender
ゲーム数学
ゲームAI
グラフィックス
サウンド
アニメーション
GBDK
制作日記
IT関連
ツール開発
フロントエンド関連
サーバサイド関連
WordPress関連
ソフトウェア設計
おすすめ技術書
音楽
DTM
楽器・機材
ピアノ
ラーメン日記
四コマ漫画
その他
おすすめアイテム
おもしろコラム
  • ゲーム開発
    • Unity
    • UnrealEngine
    • C++
    • Blender
    • ゲーム数学
    • ゲームAI
    • グラフィックス
    • サウンド
    • アニメーション
    • GBDK
    • 制作日記
  • IT関連
    • ツール開発
    • フロントエンド関連
    • サーバサイド関連
    • WordPress関連
    • ソフトウェア設計
    • おすすめ技術書
  • 音楽
    • DTM
    • 楽器・機材
    • ピアノ
  • ラーメン日記
    • 四コマ漫画
      • その他
        • おすすめアイテム
        • おもしろコラム
      1. ホーム
      2. 20231231_01_deploy_etc

      【Next.js】第四回 WordPressブログをNext.jsに移行する 〜サーバ移行・SEO・広告設定編〜

      Next.jsReactJavaScriptWordPress関連フロントエンド関連SSGStorybookEmotionNode.jsp5.js
      2023-12-31

      マイケル
      マイケル
      みなさんこんにちは! マイケルです!
      エレキベア
      エレキベア
      こんにちクマ〜〜〜
      マイケル
      マイケル
      今回、当ブログをWordPressからNext.jsで作り直しました! これまで三回に分けて実装内容を解説したのですが、最後におまけでサーバ移行やSEO設定などデプロイや運用周りで行ったこと について紹介しようかと思います!
      【都会のエレキベア】ブログを大幅リニューアル!WordPressからNext.jsに移行するまでの流れをまとめる
      2024-01-01
      【Next.js】第一回 WordPressブログをNext.jsに移行する 〜全体設計、環境構築編〜
      2023-12-31
      【Next.js】第二回 WordPressブログをNext.jsに移行する 〜WordPressデータの移行・表示編〜
      2023-12-31
      【Next.js】第三回 WordPressブログをNext.jsに移行する 〜Markdown執筆環境構築編〜
      2023-12-31

      ↑実装完了したアプリケーションを運用に向けてデプロイ・調整を行ってみる

      エレキベア
      エレキベア
      意外とその辺り書いてくれてる記事少ないクマからね・・・
      マイケル
      マイケル
      具体的には ・Netlifyへのサーバ移行 ・SEO周りの設定 ・サイト内広告の実装 の順で紹介していきます!
      マイケル
      マイケル
      また、ブログのコードについては公開できる範囲でGitHubリポジトリにも格納していますので、 よければこちらも合わせてご参照ください!

      GitHub - nextjs-elekibear-blog-scripts

      エレキベア
      エレキベア
      中々がっつり作ってあるクマね

      XServerからNetlifyへのサーバ移行

      マイケル
      マイケル
      初めはサーバ移行についてです。 今回はドメインはそのままに、XServerからNetlifyへ移行する手順になります。

      XServerのドメイン削除

      マイケル
      マイケル
      まずは元のXServerの管理画面にてドメインを削除します。 削除してから移行が完了するまではURLに接続できなくなるため、タイミングには注意する必要があります。
      20231231_01_deploy_etc_01
      ▲XServerの管理画面でドメインを削除する

      20231231_01_deploy_etc_02
      ▲ドメイン削除した時点で元のURLには繋がらなくなる

      エレキベア
      エレキベア
      これでelekibearドメインがフリーになったクマね

      Netlifyへのドメイン追加

      マイケル
      マイケル
      そのまま移行先のNetlifyの管理画面にてドメインを登録します。 それに合わせて、今回はお名前.comでドメインを取得していたため、こちらの管理設定でも紐づける必要がありました。
      20231231_01_deploy_etc_03
      ▲Netlifyでのドメイン登録

      マイケル
      マイケル
      Netlifyでドメイン登録すると、DNS設定の画面が表示されます。 それらの情報をそれぞれ www無し:Aレコード www有り:CNAMEレコード で登録すれば紐付けは完了です。
      20231231_01_deploy_etc_04
      ▲お名前.comでの設定

      20231231_01_deploy_etc_05
      ▲Aレコード、CNAMEレコードを登録する

      エレキベア
      エレキベア
      ドメイン側のDNSを設定することで移行先のサーバと紐づけるクマね
      マイケル
      マイケル
      移行自体はすぐだけど、HTTPS証明書の登録も含めてURLが正常に機能するまでにはラグがあるため注意しましょう。
      20231231_01_deploy_etc_06
      ▲HTTPS証明書もしばらくすると登録される

      エレキベア
      エレキベア
      これで新サーバに移行が完了クマ〜〜

      SEO関連の設定

      マイケル
      マイケル
      デプロイが完了したところで、SEOに必要な設定を諸々実装します。 今回は ・sitemap.xml、robots.txtの作成 ・metaタグの設定 ・GoogleAnalyticsの設定 の3つを設定しました。

      sitemap.xml、robots.txtの作成

      マイケル
      マイケル
      どちらも検索エンジンの巡回を効率化するためのもので、 sitemap.xmlはサイト内のURLを一覧化robots.txtは巡回の指示をする ための設定ファイルです。
      エレキベア
      エレキベア
      サイト内の構造を伝えることができるクマね
      マイケル
      マイケル
      こちらは様々な生成方法がありますが、今回は next-sitemap パッケージを使用して生成することにしました。 下記コマンドでインストール、設定ファイルを作成します。

      npm - next-sitemap

      # インストール
      npm install --save-dev next-sitemap
      
      # 設定ファイル生成
      touch next-sitemap.config.js
      
      マイケル
      マイケル
      ファイル内にURLやrobots.txtを生成するかを指定すれば設定は完了です。 ビルド時に next-sitemap コマンドを実行するようにすれば sitemap.xml、robots.txt がそれぞれpublicフォルダ内に作成されます。
      module.exports = {
        siteUrl: 'https://elekibear.com',
        generateRobotsTxt: true,
        sitemapSize: 7000,
      };
      
      sitemap生成の設定
      "build": "next build && next-sitemap --config next-sitemap.config.js",
      
      ▲ビルド時にnext-sitemapコマンドも追加する
      <?xml version="1.0" encoding="UTF-8"?>
      <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
      <url><loc>https://elekibear.com</loc><lastmod>2024-01-06T14:25:41.058Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
      <url><loc>https://elekibear.com/tool/madoriconvtool</loc><lastmod>2024-01-06T14:25:41.058Z</lastmod><changefreq>daily</changefreq><priority>0.7</priority></url>
      ・・・
      
      ▲出力されたsitemap.xml
      エレキベア
      エレキベア
      これだけで生成してくれるのは便利クマね

      metaタグの設定

      マイケル
      マイケル
      metaタグはWebサイトの情報を記載するタグになります。 こちらも検索エンジンに伝えられるため、SEOに関係してきます。 設定方法は簡単で、下記のようなコンポーネントを用意し、各メタタグを記事生成時に設定するようにすればよいです。
      import Head from 'next/head';
      
      /**
       * SEO用のheadメタ情報
       * @param props
       * @returns
       */
      const HeadMeta = (props: {
        title: string;
        description: string;
        url: string;
        siteName: string;
        type: string;
        imageUrl: string;
        imageWidth: number;
        imageHeight: number;
      }) => {
        return (
          <Head>
            <title>{props.title}</title>
            <meta name="description" content={props.description} />
            <meta property="og:locale" content="ja_JP" />
            <meta property="og:url" content={props.url} />
            <meta property="og:title" content={props.title} />
            <meta property="og:site_name" content={props.siteName} />
            <meta property="og:description" content={props.description} />
            <meta property="og:type" content={props.type} />
            <meta property="og:image" content={props.imageUrl} />
            <meta property="og:image:width" content={String(props.imageWidth)} />
            <meta property="og:image:height" content={String(props.imageHeight)} />
          </Head>
        );
      };
      export default HeadMeta;
      
      
      ▲受け取った情報からmetaタグを生成する
        return (
          <>
            <HeadMeta
              title={`${post.title} | 都会のエレキベア`}
              description="都会の住むエレキベアとマイケルの技術系ブログ"
              url={`https://${SiteSettings.SiteDomainName}${props.postUrlPath}`}
              siteName="都会のエレキベア"
              type="article"
              imageUrl={post.featuredImage}
              imageWidth={800}
              imageHeight={600}
            />
            <Layout
      
      ・・・略・・・
      
      
      ▲ページ生成時にmetaタグの内容を設定する
      エレキベア
      エレキベア
      記事ごとにタイトルを設定する必要があるクマね

      GoogleAnalyticsの導入

      マイケル
      マイケル
      最後にGoogleAnalyticsを設定します。 こちらはアクセス数など分析するためのツールです。 下記ページを参考にさせていただきながら設定しました。

      Qiita - 【Next.js】Next.jsにGoogle Analyticsを導入する方法

      マイケル
      マイケル
      GoogleAnalyticsに登録した後、ウェブストリームまで作成すると下記のような画面が表示されます。 こちらの測定IDを使用して実装していきます。
      20231231_01_deploy_etc_07
      マイケル
      マイケル
      「タグの実装手順を表示する」ボタンを押下すると実装するためのコードが表示されるため、こちらをNext.js用に書き直します。 lib/gtag.ts を作成し、_app.tsxにScriptタグ設定を追加します。
      import AnalyticsSettings from 'settings/AnalyticsSettings';
      
      declare global {
        interface Window {
          gtag: any;
        }
      }
      
      /**
       * この関数をページ遷移時に実行することでGoogleAnalyticsにデータを送信する
       * @param url
       */
      export const gtagPageView = (url: any) => {
        if (!window?.gtag) {
          return;
        }
        window.gtag('config', AnalyticsSettings.GoogleAnalyticsId, {
          page_path: url,
        });
      };
      
      
      ▲ページ遷移時のイベント検知処理を設定
      
      ・・・略・・・
      
      const MyApp = ({ Component, pageProps }: AppProps) => {
        // GoogleAnalyticsによる計測対応
        const router = useRouter();
        useEffect(() => {
          const handleRouterChange = (url: any) => {
            gtagPageView(url);
          };
          router.events.on('routeChangeComplete', handleRouterChange);
          return () => {
            router.events.off('routeChangeComplete', handleRouterChange);
          };
        }, [router.events]);
      
        return (
          <>
      
      ・・・略・・・
      
            {/** GoogleAnalytics広告用Script */}
            {AnalyticsSettings.IsEnableGoogleAnalytics ? (
              <>
                <Script
                  strategy="afterInteractive"
                  src={`https://www.googletagmanager.com/gtag/js?id=${AnalyticsSettings.GoogleAnalyticsId}`}
                />
                <Script
                  id="gtag-init"
                  strategy="afterInteractive"
                  dangerouslySetInnerHTML={{
                    __html: `
               window.dataLayer = window.dataLayer || [];
               function gtag(){dataLayer.push(arguments);}
               gtag('js', new Date());
      
               gtag('config', '${AnalyticsSettings.GoogleAnalyticsId}');
               `,
                  }}
                />
              </>
            ) : (
              <></>
            )}
      
      ・・・略・・・
      
        );
      };
      export default MyApp;
      
      
      ▲Scriptタグの設定
      マイケル
      マイケル
      この状態で何度かページ遷移し、GoogleAnalytics側に反映されていれば完了です!
      20231231_01_deploy_etc_08
      エレキベア
      エレキベア
      簡単クマ〜〜〜 分析は重要クマね

      サイト内広告の実装

      マイケル
      マイケル
      最後に記事内広告を導入します。 このブログはそこまで広告を貼っていないですが、最低限 ・GoogleAdsence ・Amazonアソシエイトリンク は導入しておきます。

      GoogleAdsence

      マイケル
      マイケル
      GoogleAdsenceは、Googleが提供している定番の広告サービスです。 まずは登録した際の手順に従って、ads.txtをpublicフォルダ配下に格納します。
      20231231_01_deploy_etc_11
      ▲画面の指示に従ってads.txtを配置する

      エレキベア
      エレキベア
      ここに広告配信に必要な情報が設定されているクマね
      マイケル
      マイケル
      そして次に広告ユニットを作成します。 様々な種類がありますが、ここではシンプルなディスプレイ広告ユニット、記事内広告で作成します。
      20231231_01_deploy_etc_09
      ▲ディスプレイ広告ユニットの選択

      マイケル
      マイケル
      作成すると ・クライアントID ・広告ID が確認できるため、これらを使用して実装します。 まずサイドバーウィジェット内の広告については下記のような実装になります。 こちらはディスプレイ広告の方で実装しています。
      20231231_01_deploy_etc_10
      ▲サイドバー広告ウィジェットの広告

      import { css } from '@emotion/react';
      import { useEffect } from 'react';
      import SideWidgetBase from '../WidgetBase';
      import { ElementUtil } from 'common/ElementUtil';
      import AdSettings from 'settings/AdSettings';
      
      const styleAdsWrapper = css`
        padding-bottom: 12px;
      `;
      
      declare global {
        interface Window {
          adsbygoogle: { [key: string]: unknown }[];
        }
      }
      
      /**
       * ディスプレイ広告
       * @param props
       * @returns
       */
      const AdsDisplayComponent = (props: { clientId: string; slotId: string }) => {
        useEffect(() => {
          try {
            (window.adsbygoogle = window.adsbygoogle || []).push({});
          } catch (err) {
            console.error(err);
          }
        }, []);
      
        return (
          <>
            <ins
              className="adsbygoogle"
              css={css`
                display: block;
              `}
              data-ad-client={props.clientId}
              data-ad-slot={props.slotId}
              data-ad-format="auto"
              data-full-width-responsive="true"
            ></ins>
          </>
        );
      };
      
      /**
       * 広告ウィジェット
       * @returns
       */
      const AdsWidget = () => {
        if (!AdSettings.IsEnableGoogleAdsence) {
          return <></>;
        }
      
        const clientId = AdSettings.GoogleAdsenceClientId;
        const slotId = AdSettings.GoogleAdsenceDisplaySlotId;
        if (!clientId || !slotId) {
          return <></>;
        }
      
        return (
          <SideWidgetBase title="広告">
            <div css={styleAdsWrapper}>
              <AdsDisplayComponent clientId={clientId} slotId={slotId} />
            </div>
          </SideWidgetBase>
        );
      };
      export default AdsWidget;
      
      
      ▲広告ウィジェットの実装
      エレキベア
      エレキベア
      クライアントIDと広告IDを設定して表示するのクマね
      マイケル
      マイケル
      これに加えて、ScriptタグでGoogleAdsenceのsrcを読み込むようにすれば表示されるはずです。
      
      ・・・略・・・
      
      const MyApp = ({ Component, pageProps }: AppProps) => {
      
      ・・・略・・・
      
        return (
          <>
      
      ・・・略・・・
      
            {/** GoogleAdsence広告用Script */}
            {AdSettings.IsEnableGoogleAdsence && AdSettings.GoogleAdsenceScriptSrc ? (
              <Script
                async
                src={AdSettings.GoogleAdsenceScriptSrc}
                crossOrigin="anonymous"
              />
            ) : (
              <></>
            )}
      
      ・・・略・・・
      
        );
      };
      export default MyApp;
      
      
      ▲Scriptタグの設定
      マイケル
      マイケル
      次に下記のような記事内へ挿入する広告についてです。 こちらは記事内広告を使用しますが、似たように実装することができます。
      20231231_01_deploy_etc_12
      ▲記事内広告

      import { css } from '@emotion/react';
      import { useEffect } from 'react';
      import { ElementUtil } from 'common/ElementUtil';
      import AdSettings from 'settings/AdSettings';
      
      declare global {
        interface Window {
          adsbygoogle: { [key: string]: unknown }[];
        }
      }
      
      /**
       * 記事内広告
       * @param props
       * @returns
       */
      const AdsContentComponent = (props: { clientId: string; slotId: string }) => {
        useEffect(() => {
          try {
            (window.adsbygoogle = window.adsbygoogle || []).push({});
          } catch (err) {
            console.error(err);
          }
        }, []);
      
        return (
          <>
            <ins
              className="adsbygoogle"
              css={css`
                display: block;
                text-align: center;
              `}
              data-ad-layout="in-article"
              data-ad-format="fluid"
              data-ad-client={props.clientId}
              data-ad-slot={props.slotId}
            ></ins>
          </>
        );
      };
      
      /**
       * 記事内広告アイテム
       * @returns
       */
      const AdsContentItem = () => {
        if (!AdSettings.IsEnableGoogleAdsence) {
          return <></>;
        }
      
        const clientId = AdSettings.GoogleAdsenceClientId;
        const slotId = AdSettings.GoogleAdsenceContentSlotId;
        if (!clientId || !slotId) {
          return <></>;
        }
      
        return (
          <>
            <AdsContentComponent clientId={clientId} slotId={slotId} />
            <br />
          </>
        );
      };
      export default AdsContentItem;
      
      
      ▲記事内広告の実装
      エレキベア
      エレキベア
      こっちもクライアントIDと広告IDを指定して表示するだけクマね

      Amazonアソシエイト

      マイケル
      マイケル
      もう一つ、Amazonアソシエイトという広告も使用しているのですが こちらは公式のリンク作成機能が廃止になった影響で長くなってしまったので別の記事にまとめています。 よければご参照ください!
      【Node.js】廃止されたAmazonアソシエイト画像リンクをAmazon Product Advertising API経由で復活させる
      2024-01-08
      エレキベア
      エレキベア
      廃止されたリンクを手動で復活させたのクマね・・・ 大変クマ・・・

      おわりに

      マイケル
      マイケル
      というわけで今回はサーバ移行やその他設定に関してでした! どうだったかな??
      エレキベア
      エレキベア
      サーバ移行は中々行う機会がないクマから楽しかったクマ〜〜 設定周りも情報が錯乱しているクマからまとめておくと後々助かりそうクマね
      マイケル
      マイケル
      まだ他にも設定した方がいい項目もあるだろうけど、それは後々対応していこうかと思います! これでブログリニューアルは一通り完了だから、今後も頑張っていこう!!
      エレキベア
      エレキベア
      長い道のりだったクマ〜〜〜
      マイケル
      マイケル
      それでは今日はこの辺で! アデューーー!!
      エレキベア
      エレキベア
      クマ〜〜〜〜〜

      【Next.js】第四回 WordPressブログをNext.jsに移行する 〜サーバ移行・SEO・広告設定編〜 〜完〜

      【都会のエレキベア】ブログを大幅リニューアル!WordPressからNext.jsに移行するまでの流れをまとめる
      2024-01-01
      【Next.js】第一回 WordPressブログをNext.jsに移行する 〜全体設計、環境構築編〜
      2023-12-31
      【Next.js】第二回 WordPressブログをNext.jsに移行する 〜WordPressデータの移行・表示編〜
      2023-12-31
      【Next.js】第三回 WordPressブログをNext.jsに移行する 〜Markdown執筆環境構築編〜
      2023-12-31

      Next.jsReactJavaScriptWordPress関連フロントエンド関連SSGStorybookEmotionNode.jsp5.js
      2023-12-31

      関連記事
      【ゲーム数学】第九回 p5.jsで学ぶゲーム数学「フーリエ解析」
      2024-05-12
      【Node.js】廃止されたAmazonアソシエイト画像リンクをAmazon Product Advertising API経由で復活させる
      2024-01-08
      【都会のエレキベア】ブログを大幅リニューアル!WordPressからNext.jsに移行するまでの流れをまとめる
      2024-01-01
      【Next.js】第三回 WordPressブログをNext.jsに移行する 〜Markdown執筆環境構築編〜
      2023-12-31
      【Next.js】第二回 WordPressブログをNext.jsに移行する 〜WordPressデータの移行・表示編〜
      2023-12-31
      【Next.js】第一回 WordPressブログをNext.jsに移行する 〜全体設計、環境構築編〜
      2023-12-31
      【Electron × Vue3】カテゴリ情報のCSVデータを操作するツールを作る
      2023-12-31
      【Electron × Vue3】画像をリサイズして任意の場所に保存するツールを作る
      2023-12-31