NEXT.JSチュートリアル
はじめに
自分のメモように書いています。
ページ作成
- pages/の配下で作成されたファイルがページとして表示される
- ファイルのルートがそのままリンクのパスになる
- Routeを設定しなくて良い
export default function FirstPost() {
return <h1>First Post</h1>
}
Linkコンポーネント
import Link from 'next/link'
<h1 className="title">
Read{' '}
<Link href="/posts/first-post">
<a>this page!</a>
</Link>
</h1>
import Link from 'next/link'
export default function FirstPost() {
return (
<>
<h1>First Post</h1>
<h2>
<Link href="/">
<a>Back to home</a>
</Link>
</h2>
</>
)
}
- <Link href="">で繋がれたページはprefetchされる
- アプリ内リンク遷移はaタグでも囲む
→ <Link href=""><a></a></Link> - 属性をつけるときは<a>タグに追加する
→ 書き方 - 外部URLや /pages を使ったルートナビゲーションを必要としないリンクは、Linkで処理する必要はない。→aタグのみを利用
→公式ドキュメント
※prefetchとは
事前にサーバー側で読み込まれ、表示が高速化される
Asset
静的ファイル(txt、 画像など)
• Publicディレクトリの中で静的ファイルを参照する
• Publicをルートとしたルートパスで記述
静的ファイルのパス
<img src="/〇〇.svg" alt="Vercel Logo" className="logo" />
imgディレクトリを作った場合
<img src="/img/〇〇.svg" alt="Vercel Logo" className="logo" />
Imageコンポーネント
インポートすることで利用可能になる
import Image from 'next/image'
画像の最適化
- デバイスに応じて画像サイズを自動で変更
- pngやjpegなどの形式を画像を自動でwebP
- 画像にwidthとheightを指定しても、レスポンシブ対応してくれる(アスペクト比が崩れない)
- ロードに対応(loading=lazy)
以下の記事を参考にさせていただきました。よくまとまっているので読んでみてください。
→Next.jsのnext/imageコンポーネントの使い方と注意点
<Image
src="/images/profile.jpg" // Route of the image file
height={144} // Desired size with correct aspect ratio
width={144} // Desired size with correct aspect ratio
alt="Your Name"
/>
Headコンポーネント
- Headコンポーネントをimportする
- Headコンポーネントは<head>タグに変換される
- ページごとに設定できる SEO的に良い
<link href=“”> CSSやCDNを読み込む
import Head from 'next/head'
<Head>
<title>Create Next App</title>
<link rel="icon" href="/favicon.ico" />
</Head>
Headコンポーネントのリファレンス->https://nextjs.org/docs/api-reference/next/head
pages/_document.jsでhtmlの属性をカスタマイズできる
→カスタムドキュメント
CSSスタイリング
- CSSとSassが組み込まれている
- styled-jsが組み込まれている
- style-components,emotionなどのライブラリも使用可能
- TailWindCSSの使用も可能
レイアウトコンポーネント
export default function Layout({ children }) {
return <div>{children}</div>
}
import Head from 'next/head'
import Link from 'next/link'
import Layout from '../../components/layout'
export default function FirstPost() {
return (
<Layout>
<Head>
<title>First Post</title>
</Head>
<h1>First Post</h1>
<h2>
<Link href="/">
<a>Back to home</a>
</Link>
</h2>
</Layout>
)
}
スタイルをCSS Moddulesで記述
.container {
max-width: 36rem;
padding: 0 1rem;
margin: 3rem auto 6rem;
}
CSS Modulesの特徴
• コンポーネント内で同じクラス名がなければ、ユニーク名クラス名を作成してくれる
• コンポーネント別でスタイルを変えたい時には便利
• Layoutコンポーネントでラップする
• CSS Modulesを使用するときは、CSSのファイル名の末尾に.module.css
をつける
スタイルを追加
import styles from './layout.module.css'
export default function Layout({ children }) {
return <div className={styles.container}>{children}</div>
}
global style
pages/_app.jsにglobal CSSの追加が可能、他の場所からのインポートは不可能
_app.jsについて
- _app.jsは特殊なファイルでRouteコンポーネントをラップ
- 全ページで共通して実行させたいファイルを読み込む
- 全ぺージで共通して実行させたい処理を実行する
→ 認証のリッスン Authなど - 全ページで共通のレイアウトを組み込む
export default function App({ Component, pageProps }) {
return <Component {...pageProps} />
}
import '../styles/global.css'
export default function App({ Component, pageProps }) {
return <Component {...pageProps} />
}
Pre-rendering
-
デフォルトで全てのページをpre-render
-
pre-render = 事前にHTMLを生成すること
→通常ブラウザがHTMLを読み込んでから表示される
事前に別の場所で読み込ませる。ユーザーがアクセスする前に読み込み -
通常のReactアプリだとブラウザのjsの読み込みを無効化するとアプリが表示されない
→ ブラウザがjsを読み込んでHTMLを生成するため -
ブラウザの負荷を下げて、表示を高速化
→ サーバーが事前に読み込んでくれる -
検索エンジンのクローラーにコンテンツを見せられる
→ 事前にレンダリングされてページが見つからないということが起きないため
通常だとブラウザが読み込んでいる最中にクローラーがコンテンツがないと判断してSEOがマイナス評価になる
レンダリングの種類
ひとつのアプリの中で使い分けが可能
1.Static Site Generation (SSG: 静的サイトジェネレーション)
→ ビルドされたらHTMLが事前に生成
ユーザーは皆同じページを見ることになる
表示が高速 更新頻度が低い ユーザー:コンテンツ = 1:N
例 ブログ ECサイト LP 問い合わせ
2.Server Side Rendering (SSR)
→ ユーザーがアクセスされた時にサーバー側でHTMLを生成
ユーザーがアクセスしたタイミングによっては、更新されている可能性がある
最新の状態でユーザがページを見れる
表示は遅くなる 更新頻度が高い ユーザー:コンテンツ = N:N
例 SNS チャット 動画配信 リアルタイム
3.Client Side Rendering (CSR)
→ ユーザーがアクセスした時ブラウザが読み込む
SEOを重要としないページ
例 管理画面 サービスサイト
静的ジェネレーション
-
データの有無にかかわらず実行可能
-
外部データなし
→ ビルド時にHTMLをレンダリング -
外部データあり
→ 1. ビルド時にDBや外部APIからデータを取得
2. 取得したデータを使ってHTMLをレンダリング
getStaticProos()を使う
getStaticProps
• 外部データを取得するために使う
• async/awaitを使って非同期処理を制御が可能
• 本番環境ではビルド時に実行される
• 開発環境ではリクエスト毎に実行される(npm run dev)
• pageコンポーネントでのみ使用可能
export default function Home(props) { ... }
export async function getStaticProps() {
// Get external data from the file system, API, DB, etc.
const data = ...
// The value of the `props` key will be
// passed to the `Home` component
return {
props: ...
}
}
外部データをfetchする時
export async function getSortedPostsData() {
// Instead of the file system,
// fetch post data from an external API endpoint
const res = await fetch('..')
return res.json()
}
クエリの取得
import someDatabaseSDK from 'someDatabaseSDK'
const databaseClient = someDatabaseSDK.createClient(...)
export async function getSortedPostsData() {
// Instead of the file system,
// fetch post data from a database
return databaseClient.query('SELECT posts...')
}
getServerSideProps
• リクエスト毎に実行される関数
• ServerーSide Renderingのために使う
• 外部データを取得するために使う
• Async/awaitを使って非同期処理を制御できる
• pageコンポーネントでのみ使用可能
export async function getServerSideProps(context) {
return {
props: {
// props for your component
}
}
}
SWR
• Next.jsで用意されているSWRというHooks
• Client-sideでデータを取得するなら使用を推奨
• 取得したデータを{key: value}(オブジェクト)の形でキャッシュできる
• Real-timeでデータ更新(データの再fetch)
→ 戻るを押してもデータをフェッチして最新の状態に更新
• JAMstack指向
→ 開発手法
import useSWR from 'swr'
function Profile() {
const { data, error } = useSWR('/api/user', fetch)
if (error) return <div>failed to load</div>
if (!data) return <div>loading...</div>
return <div>hello {data.name}!</div>
}
Dynamic Routes
• ファイル名に[]を使うとDynamicRoutesになる
• idによってルーティングを変える
pages/posts/[id].js
ex. URL → https://example.com/posts/[pre-rendering]
getStaticPaths
• Idが動的に変更する部分を作成する時に使用
• pathsとfallbackを返す
• Pathsは事前ビルドするパス対象を指定するパラメータ
• Fallbackは事前ビルドしたパス以外にアクセスした時の動作
import { getAllPostIds } from '../../lib/posts'
export async function getStaticPaths() {
const paths = getAllPostIds()
// オブジェクト型で返す
return {
paths,
fallback: false → trueなら事前に用意した404のサイトを見せる
}
}
→ https://nextjs.org/learn/basics/dynamic-routes/page-path-external-data
Catch-all Routes
- pages/posts/[…id].jsにファイル名を変更
- getStaticPaths()で返すidを["a", "b","c"]のような配列に変更
- posts/a, posts/a/b, posts/a/b/c を作成する
return [
{
params: {
// Statically Generates /posts/a/b/c
id: ['a', 'b', 'c']
}
}
//...
]
export async function getStaticProps({ params }) {
// params.id will be like ['a', 'b', 'c']
}
API ルート
- APIエンドポイントが作成可能
- プレビューモードで利用される
- クライアントでバンドルされない
- getStaticPropsとgetStaticPaths内でAPIは叩かない
※プレビューモードとは
static generationを利用する際、ビルド時の反映ではなく
リクエスト時にデータのフェッチを反映させるための機能
// req = HTTP incoming message, res = HTTP server response
export default function handler(req, res) {
// ...
}
APIルートで動的ページの作成方法(Dynamic API Route)
→ https://nextjs.org/docs/api-routes/dynamic-api-routes
Vercelでデプロイ
→ https://nextjs.org/learn/basics/deploying-nextjs-app/deploy
Gatsbyサイトを無料サーバーVercelで公開する方法を徹底解説
学習の際は以下のYouTubeを参考にさせていたただきました。
とてもわかりやすく解説されているのでおすすめです。
Discussion