next.js: チュートリアルからの覚書(基本的な利用方法、CSS設定、ルーティングなど)
チュートリアルをせっかくクリアしても、習ったそばから忘れてしまうのでメモ書き。チュートリアルを網羅しているわけではなく、自分が使う内容だけ抜き出している点に注意。
環境: Next.js 12.2.5
Next App作成
Nextを利用したApplicationを作る方法。
npx create-next-app@latest
# TypeScriptを利用する場合
npx create-next-app@latest --ts
yarn
や pnpm
の場合は以下参照
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-layout の layout.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には以下が記述されている必要がある。
getStaticPaths
: そのファイルが対応するすべてのパスを列挙するgetStaticPaths
: そのファイルが表示するデータを引き渡す
1.でその動的ルーティング向けpageで対応できるパスをすべて列挙する必要がある。何を列挙するかというと、ファイル名に入っている引数に入るものを列挙する。 [id].js
であれば id
として入るデータをすべて入れる。特定ディレクトリの *.md
ファイルをすべて見せたいのであれば、そのファイルを列挙して入れていく形になる。
2.についてはサーバサイドレンダリングにも出てきた通りで、表示内容を渡す必要がある。ファイル名の引数を受け取り、引数に応じたデータを返すように作る。
Markdown の表示
単にコードをコピペするだけになりそうだったので、割愛。以下を参照。
https://nextjs.org/learn/basics/dynamic-routes/render-markdown
dangerouslySetInnerHTML
にだけコメントを加えておくと、これは通常のJavascriptでも存在する innerHTML
をReactが置き換えたもので、JSを利用してHTMLのコンテンツを書き換えるのは危険が伴うということを常に開発者にリマインドするためのものらしい。
以上
自分が必要な情報のみ抜き書きしておいた。
コメント
コメントを投稿