next.js: チュートリアルからの覚書(基本的な利用方法、CSS設定、ルーティングなど)

チュートリアルをせっかくクリアしても、習ったそばから忘れてしまうのでメモ書き。チュートリアルを網羅しているわけではなく、自分が使う内容だけ抜き出している点に注意。

環境: Next.js 12.2.5

Next App作成

Nextを利用したApplicationを作る方法。

npx create-next-app@latest
# TypeScriptを利用する場合
npx create-next-app@latest --ts

yarnpnpm の場合は以下参照
https://nextjs.org/docs/api-reference/create-next-app

基本動作

<head> の書き換え

Head コンポーネントを利用することで <head> タグの中身を書き換えることができる。

import Head from 'next/head';

https://nextjs.org/docs/api-reference/next/head

外部スクリプトの読み出し

通常であれば <head> 内部などに <script> タグを書くことで読みだすが、 Script コンポーネントを利用する。

Head コンポーネントの外に記述する必要がある点に注意。

import Script from 'next/script';

ロードの遅延(defer)設定や読み込み完了時のフックなどを記述できる。

<Script
  src="https://xxxxx.xxxx.com/xxxx.js"
  strategy="lazyOnload"
  onLoad={() =>
    console.log(`script loaded correctly`)
  }
/>

https://nextjs.org/docs/api-reference/next/script

リンクを貼る

特別な理由がない限り、<a> タグではなく Link コンポーネントを利用する。これにより Next.js の強みである prefetch が適切に行われるため。

Link コンポーネントの為にはまず import が必要。

import Link from 'next/link';

後は通常通り href でリンク先を設定する。

https://nextjs.org/docs/api-reference/next/link

サイト全体のレイアウト / テンプレートの作成

レイアウト / テンプレートという概念は厳密にはないが、 Rails でいう レイアウト 、 Djangoでいうテンプレートのような気持ちでもって全ページ共通の部分を作成する方法。例えばヘッダーやフッター、サイドバーおよび <head> に共通で埋め込みたい情報など。

components などのディレクトリを作成し、その中に新たなコンポーネントの定義ファイルを作成。そのコンポーネントがサイトの全体構成と、その中に子ノードの情報をを含めた状態のデータを返却するようにする。

そしてそのほかの page において上記作成したコンポーネントで囲むようにする。

文字だけだと何を言っているかわからないかもしれないので、具体的には https://nextjs.org/learn/basics/assets-metadata-css/polishing-layoutlayout.js を作成・利用しているあたりを参照。

Asset / Metadata / CSS

CSS Module

*.module.css というファイルを作成しその中にCSSを記述。

このファイルをほかの JavaScriptファイルから <*部分>Style という名称で import すると、 *.module.css の中のクラス名として指定できるようになる。

https://nextjs.org/learn/basics/assets-metadata-css/polishing-layout

Global Styling

CSS Moduleではコンポーネントレベルのスタイリングを実施できる。ではサイト全体で統一したスタイリング(global CSS)を適用するにはどうするか。

global CSSを適用するには、 pages/_app.js というファイルを作成する必要がある。このファイルの中で App というコンポーネントを以下のように定義する。 App はすべてのページで共通に使われるコンポーネントであるようだ。

import '../styles/global.css';

export default function App({ Component, pageProps }) {
  return <Component {...pageProps} />;
}

上記コードで参照されている styles/global.css を作成し、その中に自分が適用したいCSSを記述する。このファイルは pages/_app.js 以外からは import することができない。まぁすることもない気はするけど。

上記 pages/_app.js を作成したら、npmで起動させているサーバを再起動する。

npm run dev

そのほかの事項

CSSのコンパイル動作を変える

Tailwind CSS などを利用する際に使うらしい。よくわからないのでスキップ。

Sass を使いたい人

npm install -D sass

をしてから、css の拡張子を sass / scss に変える。

表示するコンテンツをどこか別の場所から取り出す方法

「どこか別の場所」というのは、ファイルシステムやどこかのサイトのAPI、データベース1など。JSファイルの外という意味。

静的なコンテンツを表示するサイトを生成する場合

事前

Markdownの中に記述されている front-matter という形式のメタデータを取り扱うライブラリが必要となるので入れる。(Markdownをレンダリングするライブラリではない)

npm install gray-matter

https://github.com/jonschlinkert/gray-matter

データをどこかからとってくる方法

データの取り出しを行いたい js ファイルを開き、その中にgetStaticProps 2という関数を作成し任意のデータを props に詰めて返す。本関数は名前の通り static に動くので、build 時に動作するため動的な処理は行えない。

下記の XXXX という関数の部分に何を書くかはチュートリアルでファイルシステムからデータを取り出しているところが参考になる。必要ならばAPI経由、データベースクエリによってデータを取り出しているところも参照。

export async function getStaticProps() {
  /* ここでは XXXX() という別の関数でデータ処理をしている想定 */
  const my_data= XXXX();
  return {
    props: {
      my_data,
    },
  };
}

この props が適切にレンダリング関数でハンドルされるように関数の中身を修正する。Destructuring Assignment(分割代入) を利用。

別に分割代入せず、 props をそのまま受け取るような形にしても問題はない。

export default function Home({ my_data }) {
  ...  /* 何かmy_dataを処理してDOMを返す */
}

動的コンテンツを表示するサイトの構築

動的コンテンツとは、ユーザから送られてくるデータに応じて表示内容を変えるなどの対応を実施するということ。

サーバサイドレンダリングによる方法

上述の getStaticProps の代わりに getServerSideProps を実装する。やる内容は一緒だが、受け取る引数が異なる。本関数はユーザからのリクエスト時に動作する。

export async function getServerSideProps(context) {
  return {
    props: {
      // props for your component
    },
  };
}

注意点として、この関数に記述するのはプリレンダされたページとして表示する必要があるデータにとどめること。リクエスト時に実行されるため処理によってはレスポンス時間が遅くなる可能性がある。

クライアントサイドによる方法

動的サイトと言えば、の方式。最低限必要な部分はプリレンダし、それ以外はAPI経由でクライアントから取り出し、クライアント側でレンダリングをする方式。

SWR というものを利用すると簡単らしい。 (ノータッチ)

動的ルーティング

静的サイトを作るにしても、すべてのページを個別に自分で作成し、 export default function みたいなことを書いていくわけにもいかない。たとえば Markdown ファイルを配置していたら自動でページを生成してほしい。そういったときに動的ルーティングを使用する。

事前

Markdownをレンダリングするために以下を入れる。

npm install remark remark-html

メモ:
remark は Markdownを解析しAST(Abstract Syntax Tree) に分解するためのライブラリで、 remark-html はそれをHTMLとして生成するためのもの。

ファイルを作成する

動的ルーティングを利用して表示するには、それ用の page を作成する必要がある。

ファイル名に引数を [] で囲って含めておく必要がある。 [id].js とか [name].js とかになる。前者ならば id という引数を取って自動生成するページであり、後者なら name という引数を取って自動生成するページである。

Catch-all Routes

... 記法をファイル名に組み込むことで、ディレクトリも含めて変数として取り出すことができる。

[...id].js というファイルを作成すると、そのpageがあるディレクトリに a/b/c/test.js というファイルを作成すると id = ['a', 'b', 'c', 'test'] という配列として解釈される。

必要な関数の実装

動的ルーティング向けのpageには以下が記述されている必要がある。

  1. getStaticPaths : そのファイルが対応するすべてのパスを列挙する
  2. getStaticPaths : そのファイルが表示するデータを引き渡す

1.でその動的ルーティング向けpageで対応できるパスをすべて列挙する必要がある。何を列挙するかというと、ファイル名に入っている引数に入るものを列挙する。 [id].js であれば id として入るデータをすべて入れる。特定ディレクトリの *.md ファイルをすべて見せたいのであれば、そのファイルを列挙して入れていく形になる。

2.についてはサーバサイドレンダリングにも出てきた通りで、表示内容を渡す必要がある。ファイル名の引数を受け取り、引数に応じたデータを返すように作る。

Markdown の表示

単にコードをコピペするだけになりそうだったので、割愛。以下を参照。

https://nextjs.org/learn/basics/dynamic-routes/render-markdown

dangerouslySetInnerHTML にだけコメントを加えておくと、これは通常のJavascriptでも存在する innerHTML をReactが置き換えたもので、JSを利用してHTMLのコンテンツを書き換えるのは危険が伴うということを常に開発者にリマインドするためのものらしい。

以上

自分が必要な情報のみ抜き書きしておいた。


  1. サーバーサイドで処理を行う関数の記述を実施するので、データベースにクエリを投げることもできる。 ↩︎

  2. この関数は page からのみ呼び出すことができる。別のファイルに書いておいて import するという方式はとれないらしい。 ↩︎

コメント

このブログの人気の投稿

gnuplot: グラフの色を変更する

[Linux] rsyncで進捗を確認する

gnuplotで縦線を引きたい