YuTa Extend

YuTaの個人開発と趣味のブログ

【入門】ブログ開発に使えるNext.jsの基本コードいろいろ

2022-05-22  

blog-002-nextjs-basics

はじめに

Next.js で基本となるページ遷移やコンポーネントの実装方法を紹介します。 Next.js の環境構築や始め方については、前回のブログを参照ください。

【作成ケース ①】コンポーネントを使って複数のページで同じ内容を表示させる

ヘッダーやフッターなど、複数のページで同じ内容を表示させたいものについては、 コンポーネント という部品に分けてコードを記述できます。srcフォルダの下にcomponentsという名前でフォルダを作成し、そのフォルダ内に以下のようにファイルを作成します。

src/components/header.tsx
Copied!!
const Header: React.FC = () => {
  return (
    <header>
      <p>ヘッダー</p>
    </header>
  );
};

export default Header;
src/components/footer.tsx
Copied!!
const Footer: React.FC = () => {
  return (
    <footer>
      <p>フッター</p>
    </footer>
  );
};

export default Footer;
src/components/layout.tsx
Copied!!
import Header from "./header";
import Footer from "./footer";
import { ReactNode } from "react";

type Props = {
  children?: ReactNode;
};
const Layout: React.FC<Props> = ({ children }: Props) => {
  return (
    <>
      <Header />
      {children}
      <Footer />
    </>
  );
};

export default Layout;

また、作成した<Layout>コンポーネントは_app.tsxファイルに以下のように記述すると全ページに適用できます。

src/pages/_app.tsx
Copied!!
import "../styles/globals.css";
import type { AppProps } from "next/app";
import Layout from "../components/layout";

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <Layout>
      <Component {...pageProps} />
    </Layout>
  );
}

export default MyApp;

ここまでのコードでnpm run devで画面に表示すると、以下のような画面が表示されるかと思います。

header-footer

【作成ケース ②】他のページを追加してリンクを張る

Next.js では、他のページを追加してリンクを張ることが簡単にできます。 以下のようにpagesフォルダの下にファイルやフォルダを追加していけば、それがそのままリンク先のページになります。 また、リンクを張るには、以下のように最初の行にimport Link from "next/link"と記述し、リンクを張りたい部分を<Link>タグと<a>タグで囲えば OK です。

src/pages/about.tsx
Copied!!
import type { NextPage } from "next";
import Link from "next/link";

const About: NextPage = () => {
  return (
    <>
      <h2>About Page!!</h2>
      <Link href="/">
        <a>Home Pageへのリンク</a>
      </Link>
    </>
  );
};

export default About;
src/pages/index.tsx
Copied!!
import type { NextPage } from "next";
import Link from "next/link";

const Home: NextPage = () => {
  return (
    <>
      <h2>hello world!!</h2>
      <Link href="/about">
        <a>About Pageへのリンク</a>
      </Link>
    </>
  );
};

export default Home;

今度は以下の画面が表示されるかと思います。About Page へのリンク をクリックすると、About ページに遷移します。

create-link

【作成ケース ③】画像ファイルを表示する

画面に表示する画像ファイルはpublicフォルダ内に格納できます。 このとき下記のようにnext/imageの Image コンポーネントを<img>タグの替わりに使うと、画面に合わせて画像を最適なサイズに縮小し、遅延ロードによって画面を読み込んだ後に表示してくれるようになります。

まず以下のようにファイルを格納します。

Copied!!
/public
 └─ sample.jpg

次にindex.tsxにて Image コンポーネントを使ってみます。

src/pages/index.tsx
Copied!!
import type { NextPage } from "next";
import Link from "next/link";
import Image from "next/image";

const Home: NextPage = () => {
  return (
    <>
      <h2>hello world!!</h2>
      <Link href="/about">
        <a>About Pageへのリンク</a>
      </Link>
      <Image
        src="/sample.jpg"
        width={400}
        height={300}
        objectFit="contain"
        alt="sample"
      />
    </>
  );
};

export default Home;

view-image

なお、現状の Cloudflare Pages ではnext/imageデフォルトのイメージローダー という機能が使えません。そのままデプロイしようとすると以下のようなエラーが発生します。

Copied!!
Error: Image Optimization using Next.js' default loader is not compatible with `next export`.

なので、Cloudflare Pages にデプロイするソースでnext/imageを使う場合は以下のようにイメージローダーの設定が必要になります。(Vercel ではイメージローダーがデフォルトのままでも補完してくれるので、Vercel にデプロイする場合は以下の設定は不要です) まずはnext.config.jsファイルを編集します。(赤波のエラーが発生するかもしれませんが、ひとまず無視で大丈夫です。)

next.config.js
Copied!!
/** @type {import('next').NextConfig} */
module.exports = {
  reactStrictMode: true,
  images: {
    loader: "custom",
  },
};

次に以下のコンポーネントをcomponentsフォルダに作成します。そして実際にnext/imageの Image コンポーネントを使いたい場所では、next/imageではなくこのコンポーネントを import するようにします。loader属性に入力されたsrcwidthを入れているだけで暫定ではありますが、とりあえずこれでnext/imageの Image コンポーネントを動作させることができます。

src/components/Image.tsx
Copied!!
import NextImage from "next/image";

const customLoader = ({ src, width }: any) => {
  return `${src}?w=${width}`;
};
const Image = ({ ...props }: any) => {
  return <NextImage {...props} loader={customLoader} />;
};

export default Image;
src/pages/index.tsx
Copied!!
import type { NextPage } from "next";
import Link from "next/link";
import Image from "../components/Image";

const Home: NextPage = () => {
  return (
    <>
      <h2>hello world!!</h2>
      <Link href="/about">
        <a>About Pageへのリンク</a>
      </Link>
      <Image
        src="/sample.jpg"
        width={400}
        height={300}
        objectFit="contain"
        alt="sample"
      />
    </>
  );
};

export default Home;

なお、今回作成したサンプルについては、以下の GitHub のリポジトリに全コードを格納してありますので、詰まったら参考にしてみてください。

https://github.com/YuTaExtend/nextjs-basics

関連記事

blog-001-nextjs-ssg-blog

【入門】Next.jsを使って0からブログを作成する

Next.jsでブログを作りました。この方法はコーディングが必要なため手間はかかりますが、安価でハイパフォーマンスなフルカスタマイズのサイトを作れるメリットがあります。本記事では実際に Next.js を使ってブログを作成し、それを GitHub 経由で Cloudflare Pages にデプロイして公開するまでの流れを紹介します。... 続きを読む

2022-05-21