クモのようにコツコツと

フロントエンドエンジニア イイダリョウの技術ブログ。略称「クモコツ」

【React】Next.jsのリンク設定(Link)、共通コンポーネント化、headタグ設定(Head)

Next.jsの続きです。前回はNext.jsアプリをVercelにデプロイしました。今回はLinkによるリンク設定、ヘッダー・フッターなどの共通部分のコンポーネント化、Headコンポーネントによるheadタグ設定をそれではいきましょう!

【目次】

※参考:前回記事
【React】Next.jsのデプロイ:Vercelがまったく・カン・タンだ! - クモのようにコツコツと

※参考:Reactを習得するためにやったことまとめ
qiita.com

前回のおさらい

Next.jsアプリをビルドし、GitHub Pagesへのデプロイを検討したが、最終的にVercelにデプロイ

https://cdn-ak.f.st-hatena.com/images/fotolife/i/idr_zz/20210421/20210421064421.jpg

※参考:前回記事
【React】Next.jsのデプロイ:Vercelがまったく・カン・タンだ! - クモのようにコツコツと

Next.jsの修正は開発モード(npm run dev)で

ローカル環境、いつものように下記のコマンドで起動する。

$ npm start

しかし、修正がブラウザ上に反映されない、、?


ビルドすると修正が反映される。

$ npm run build

修正のたびにブルドするのは手間だなー…

似たような事例があった。「開発モード」で作るとよさそう?

※参考:Node.js - next.js いちいちbuildコマンドを打たなければならないのでしょうか?|teratail


ドキュメントを見るとnextスクリプトが開発モードのようだ

dev - nextは Next.js を開発モードで実行します。
build - next buildは本番用にアプリケーションをビルドします。
start - next startは Next.js の本番サーバーを起動します。

※参考:はじめに | Next.js


nextスクリプトはpackage.jsonで下記のコマンドにnext devコマンドを設定している。

※参考:【React】Next.jsを事始める(インストール、ページ設定、表示まで) - クモのようにコツコツと

開発モードで起動!

$ npm run dev

これで修正が反映されるようになった♪

リンクをaタグからLinkに変更

こちらの記事にNext.jsの基本的な機能がピックアップされていたので参考にする。

※参考:Next.jsの基礎 - Qiita


前回、別ページにaタグでトップページに戻るリンクを設定した。

function Other() {
    return <div>
            <p>ここは別のページだよ〜ん</p>
            <p><a href="/">戻る</a></p>
        </div>;
  }

  export default Other;

これでも動くのだが、ページ全体がリロードになる。

Next.jsのLinkコンポーネントを使うとページの変更部分のみがレンダリングされるようだ!

※参考:next/link | Next.js


Linkコンポーネントをインポート

import Link from 'next/link';

aタグをLinkで囲って、href属性はLinkの中に書く。

function Other() {
    return <div>
            <p>ここは別のページだよ〜ん</p>
            <Link href="/"><a>戻る</a></Link>
        </div>;
  }

Topページも同様に別ページへのリンクを追加してみる。

import Link from 'next/link';

 function HomePage() {
     return <div>
             <p>ねくすと・じぇいえす事始め!</p>
             <Link href="/other"><a>別ページへ</a></Link>
       </div>;
   }

ブラウザ挙動

Topページと別ページに相互に行き来できる。
f:id:idr_zz:20210423060903j:plain
f:id:idr_zz:20210423060913j:plain
しかもページ全体のリロードではなく、SPA的にページの変更部分のみがレンダリングされて、サクサク動く!

ヘッダー、フッターのコンポーネント化

ページ間を行き来するために、各ページにリンクを追加するのではなく、ヘッダーに共通のメニューをおきたい。ヘッダー、フッターなどの共通要素はコンポーネント化して配置したい。

「/components」フォルダを作ってその中に「Header.jsx」「Footer.jsx」を作る。 f:id:idr_zz:20210423061302j:plain

Next.jsの特別なフォルダはページ設定の「/pages」フォルダと静的ファイルを入れる「/public」フォルダ

※参考:Basic Features: 静的ファイルの配信 | Next.js

それ以外のフォルダは自由に作っていい。


Headerコンポーネント(Header.jsx)

import Link from 'next/link';

 function Header() {
     return <header>
             <h1>ねくすと・じぇいえす事始め!</h1>
             <menu>Menu:
                 <Link href="/"><a>トップ</a></Link>|
                 <Link href="/other"><a>別ページ</a></Link>
             </menu>
       </header>;
   }

   export default Header;

Linkコンポーネントをインポートして、headerタグのmenuのリンクをLinkで作成


Footerコンポーネント(Footer.jsx)

function Footer() {
    return <footer>
            <p>©️イイダリョウ</p>
      </footer>;
  }

  export default Footer;

こちらはfooterタグのみ。


トップページ(index.js)

HeaderFooterコンポーネントをインポート

import Header from '../components/Header';
 import Footer from '../components/Footer';

HeaderFooterを配置

function HomePage() {
     return <div>
             <Header />
             <section>
                 <h2>トップページ</h2>
                 <p>Next.jsの世界にようこそ!</p>
                 <Link href="/other"><a>別ページへ</a></Link>
             </section>
             <Footer />
         </div>;
   }

別ページ(other.js)

こちらもHeaderFooterコンポーネントをインポート

import Header from '../components/Header';
 import Footer from '../components/Footer';

HeaderFooterを配置

function Other() {
     return <div>
             <Header />
             <section>
                 <h2>別ページ</h2>
                 <p>ここは別のページだよ〜ん!</p>
                 <Link href="/"><a>戻る</a></Link>
             </section>
             <Footer />
         </div>;
   }

ブラウザ挙動確認

トップページにヘッダー・フッターが表示された!
f:id:idr_zz:20210423065050j:plain
別ページにも!
f:id:idr_zz:20210423065105j:plain
ページ間の行き来もメニューから問題なくいける。

headタグにtitle、descriptionを設定

次にページ毎に固有のtitle、descriptionを設定した。ReactのときはHelmetを使った。

※参考:【React】react-helmetでheadタグの中身を動的に打ち替える(Reactとメタ言語の比較-2) - クモのようにコツコツと

Helmetはブラウザ側での動的のレンダリングのため、OGPに反映されなかった…。

※参考:【React】OGPはつらいよ ーSPAでの動的OGP・失敗編ー(Reactアプリスターターキット) - クモのようにコツコツと


Next.jsにはHeadコンポーネントが用意されており、headタグの設定はここに書くようだ。

※参考:next/head | Next.js


トップページ(index.js)

Headコンポーネントをインポート

import Head from 'next/head';

共通する文字列を変数textに連想配列で設定

const text = {
     title: 'トップページ',
     desctiption: 'Next.jsの世界にようこそ!'
 };

Headコンポーネントを配置し、title、descriptionを設定(共通テキストはtextを配置)

function HomePage() {
    return (
        <div>
            <Head>
                <title>{ text.title }</title>
                <meta name="description" content={ text.desctiption } />
            </Head>
            <Header />
            <section>
                <h2>{ text.title }</h2>
                <p>{ text.desctiption }</p>
                <Link href="/other"><a>別ページへ</a></Link>
            </section>
            <Footer />
        </div>
    );
  }

別ページ(other.js)も同様の処理

Headコンポーネントをインポート

import Head from 'next/head';

共通テキストをtextに設定

const text = {
     title: '別ページ',
     desctiption: 'ここは別のページだよ〜ん!'
 };

Headコンポーネントを配置し、title、descriptionを設定(共通テキストはtextを配置)

function Other() {
    return (
        <div>
             <Head>
                <title>{ text.title }</title>
                <meta name="description" content={ text.desctiption } />
            </Head>
            <Header />
            <section>
                <h2>{ text.title }</h2>
                <p>{ text.desctiption }</p>
                <Link href="/"><a>戻る</a></Link>
            </section>
            <Footer />
        </div>
    );
  }

ブラウザ挙動

トップページ f:id:idr_zz:20210423065050j:plain

※参考:トップページ

Dev-toolsのSourcesパネル
f:id:idr_zz:20210423065535j:plain
うむ、ちゃんと値が入っている(Helmetは動的レンダリングなのでここに入らなかった)

別ページに遷移して…
f:id:idr_zz:20210423065105j:plain

Dev-toolsのSourcesパネルを見ると…
f:id:idr_zz:20210423065149j:plain
ありゃ?トップページのままだぞ、、?

Elementsパネルで見るとちゃんと別ページの内容になってるんだけどなー(Helmetの二の舞か?)
f:id:idr_zz:20210423065811j:plain

ページをリロードしてみると、お、Sourcesパネルも別ページの内容になった♪
f:id:idr_zz:20210423065827j:plain

※参考:別ページ

画面表示上はSPA的にサクサク切り替えるけど、headタグにはちゃんと静的な値が入るため、検索botやSNSシェア(OGP)ではソースの方が優先されるんだな。


ここまでのコミット

※参考:GitHub - ryo-i/next-test at 8830222ebca90b466fbc1a2c8ae4c8baabc72c1a

プレビュー

※参考:トップページ

最後に

ということでNext.jsの基本的な部分を体験してみましたー。

  • Link:SPA的にサクサクページ遷移できる
  • 共通コンポーネント化:Reactと同じ使い心地で問題なし
  • Head:Helmetと違って静的な値が設定される

Next.jsに用意されているLinkHeadはReactのメリット、デメリットが相克されてて素晴らしいですね!これでOGPも設定できそうに思います。

次はNext.jsの「Create Next App」を体験してみたく思います。Create React Appに名前が似ていますね。

それではまた!


※参考:Reactを習得するためにやったことまとめ
qiita.com