Next.js入門

24994 ワード

Next.jsはじめての環境構築備忘録
公式をメインにまとめ
編集中

実施環境
項目 詳細
PC MacBook Pro(14インチ、2021)Apple M1 Pro
OS MacOS Monterey 12.3
Node.js v16.14.2(インストール済み前提)
Next.js v12.1.5

Next.js 概要

オープンソースで提供されるReactベースのフロントエンドフレームワーク。
Reactでの開発に必要な機能(SSRやルーティングなど)をあらかじめ備えている。

Hello world

プロジェクトの生成

create next-appでプロジェクト生成可能。
--tsオプションでtypescript追加。(--typescriptでも可)
プロジェクト名を聞かれるので、好きな名前を設定。

プロジェクト生成
npx create-next-app@latest --ts
# or
yarn create next-app --ts

その後、下記でデフォルトページ表示可能。
デフォルトでは http://localhost:3000 でアクセス可能。

起動
cd プロジェクト名
yarn dev

CSSの選択肢

大きく下記があるらしい

  • Pure CSS
  • CSS Modules
  • CSS-in-js

Pure CSS

設定不要

Button.css
.button {
  background-color: green;
}
Button.tsx
import { VFC } from 'react';
import './Button.css';

type ButtonProps = {
  title: string;
};

export const Button: VFC<ButtonProps> = ({title}) => {
  return <button className="button">{title}</button>
};

ただ、componentsでimportしようとすると怒られる。

./src/components/partials/Button.css
Global CSS cannot be imported from files other than your Custom <App>. Due to the Global nature of stylesheets, and to avoid conflicts, Please move all first-party global CSS imports to pages/_app.js. Or convert the import to Component-Level CSS (CSS Modules).
Read more: https://nextjs.org/docs/messages/css-global
Location: src/components/partials/Button.tsx

_app.*tsxでimportするといける。
つまりグローバル管理になってしまうため、コンポーネントベースという思想とは合わなそう。

あとはtsxファイル内に書いてしまうか。
こちらの方がまだマシ。
だだしこれも推奨されないとのこと。

Button.tsx
import { VFC } from 'react';

type ButtonProps = {
  title: string;
};

const style = {
  backgroundColor: "green",
}

export const Button: VFC<ButtonProps> = ({title}) => {
  return <button style={style}>{title}</button>
};

つまりReactのプロジェクトで各ページのスタイリングに素のCSSを使うことはほとんどないと思われる。たぶん。(グローバルに当てたいスタイルは上記で記述する。reset cssとか。)

CSS Modules

Next.jsのビルドインサポート。

Button.module.css
.button {
  background-color: green;
}
Button.tsx
import { VFC } from 'react';
import style from './Button.module.css';

type ButtonProps = {
  title: string;
};

export const Button: VFC<ButtonProps> = ({title}) => {
  return <button className={style.button}>{title}</button>
};

古い技術で、css-loaderでdeprecatedになりそうらしい。
ただ今の所Next.jsビルドインサポートしているし、問題はなさそう。

CSS-in-JS

いくつか種類があり、styled-components, emotionあたりが有名。

試しにstyled-componentsを使ってみる。

インストール
yarn add styled-components
yarn add --dev @types/styled-components

書き方

Button.tsx
import { VFC } from 'react';
import styled from "styled-components"

type ButtonProps = {
  title: string;
};

export const Button: VFC<ButtonProps> = ({title}) => {
  const Button = styled.button`
    background-color: green;
  `

  return <Button>{title}</Button>
};

CSS modulesとの違い

  • tsxファイルとcssファイルを一つにまとめられる
  • テンプレートリテラルでの指定のため、動的に変更できる

CSS-in-JS良さそうと思うが、CSS ModulesがNext.jsのビルドインサポートなのはいろいろ理由があるらしい。

ページの追加

ルーティング

Next.jsでは、pagesフォルダ配下のディレクトリ構造がそのままページURLになる。

  • pages/index.js -> https://{あなたのドメイン}/
  • pages/posts/first-post.js -> https://{あなたのドメイン}/posts/first-post
  • pages/posts/[pageId].js -> https://{あなたのドメイン}/posts/{ページID}
    • これは動的なルーティングのケースでページIDによって出し分けるような場合に使う
    • 例えば、 https://{あなたのドメイン}/posts/a123 の場合、下記 pageId が a123 になる
/pages/posts/[pageId].js
import { useRouter } from 'next/router';

const Posts = () => {
  const router = useRouter();
  const { pageId } = router.query;

  return <p>Post: {pageId}</p>;
};

export default Post;

リンク

Next.jsではaタグの利用は非推奨で、Linkコンポーネントを使う。
Linkコンポーネントを使えば、クライアントサイドで遷移ができる。
aタグを使うと、毎回フロントサーバにリクエストを投げることになる。

※ただし外部リンクの場合はaタグを使用する

リンクコンポーネント
import Link from 'next/link'

export default function FirstPost() {
  return (
    <>
      <h1>First Post</h1>
      <h2>
        <Link href="/">
          <a>Back to home</a>
        </Link>
      </h2>
    </>
  )
}

動的なルーティングのケース

動的ルーティング
import Link from 'next/link'

function Posts({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>
          <Link href={`/blog/${encodeURIComponent(post.slug)}`}>
            <a>{post.title}</a>
          </Link>
        </li>
      ))}
    </ul>
  )
}

export default Posts

Linkコンポーネントの詳細はこちら

code splitting

Next.jsではあるページにアクセスした場合、そのページに必要なコードのみがロードされる。
それによってページの独立性が保たれ、速度も上がる。
ただし、そのページ上にLinkタグがある場合、その先のページのロードをバックグラウンドで行う。
そのため、ページ遷移自体はクライアント側で実施され、高速な遷移を実現できるらしい。(プロダクションビルド時のみ)

Assets

画像など

画像などは public フォルダ内に配置し、下記の様に使用

public/images/profile.jpgの画像
<img src="/images/profile.jpg" alt="Your Name" />

publicフォルダは robots.txtfavicon.ico などの配置にも適している。素のHTMLなんかをおいても大丈夫。詳細はこちら

Imageコンポーネント

Next.jsには画像関連をいろいろと最適化してくれるImageコンポーネントがある。

  • スクリーンサイズごとの最適化
  • WebPなどの最新フォーマットのサポート

などなど
詳細はこちら

Imageコンポーネント
import Image from 'next/image'

const YourComponent = () => (
  <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"
  />
)

参考