これまで一度もNext.jsを触ったことがないけど興味があるまた今後使ってみたいという人を対象にNext.jsの基礎について説明を行っています。

本文書を読み終えると下記のことを理解することができます

  • Next.jsのインストール方法
  • 静的ファイルの作成方法
  • 動的ファイルの作成方法
  • ページ間のリンクの設定方法
  • 外部からのデータ取得と表示(getStaticProps, getServerSideProps)
  • styled-jsxによるCSSの適用方法

Next.jsをインストールするためには事前に Node.jsのインストールを完了しておく必要があります。

環境:macOS Catalina バージョン10.15.6、Next.jsはバージョンは9.5.3です。

Next.jsのインストール

npxコマンドを利用してnext.jsのインストールを行います。


 % npx create-next-app

プロジェクトの名前を聞かれるので任意のプロジェクト名を入力してください。デフォルトの名前のまま進む場合はEnterを押します。コマンドを実行したディレクトリに任意の名前もしくはmy-appディレクトリが作成されます。

インストール中にエラー発生

※下記のエラーは環境に依存するエラーがだと思いますので発生しない場合はスキップしてください。

インストール処理は最後までいきその後にnpm run devコマンドを実行してもNext.jsの初期画面は表示されるのですが、インストールログに下記のエラーが表示されていることを確認。


gyp: No Xcode or CLT version detected!
gyp ERR! configure error 
gyp ERR! stack Error: `gyp` failed with exit code: 1
gyp ERR! stack     at ChildProcess.onCpExit (/usr/local/lib/node_modules/npm/node_modules/node-gyp/lib/configure.js:351:16)
gyp ERR! stack     at ChildProcess.emit (events.js:314:20)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:276:12)
gyp ERR! System Darwin 19.6.0
gyp ERR! command "/usr/local/bin/node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /Users/mac/Desktop/my-app/node_modules/fsevents
gyp ERR! node -v v14.7.0
gyp ERR! node-gyp -v v5.1.0
gyp ERR! not ok 

command line toolsに問題が発生しているということなのでパスを確認して削除を行います。


 % xcode-select --print-path
/Library/Developer/CommandLineTools
 % sudo rm -rf /Library/Developer/CommandLineTools

削除後commend line toolsのインストールを行うため下記のコマンドを実行しますが、”このソフトウェアは、現在ソフトウェア・アップデート・サーバから入手できないため、インストールできません。”と表示されインストールすることができませんでした。


 % xcode-select --install

Appleのサイト(https://developer.apple.com/download/)から手動でインストールすることができるということなので、アクセスを行います。アクセスにはApple IDが必要となります。

下記のCommand Line Tools for Xcode 12をダウンロードしてインストールを行います。

Appleのサイトからダウンロード
Appleのサイトからダウンロード

一度npx create-next-appコマンドで作成されるmy-appディレクトリを削除再度npx create-next-appコマンドを実行すると今回はエラーなしでインストールが完了しました。

next.js開発サーバの起動

インストール中に表示されるメッセージの中にnpmの3つのコマンドの説明があります。


Success! Created my-app at /Users/mac/Desktop/my-app
Inside that directory, you can run several commands:

  npm run dev
    Starts the development server. //開発時に実行。開発サーバを起動

  npm run build
    Builds the app for production. //本番用にビルドを行う

  npm start
    Runs the built app in production mode.// 本番用にビルドしたアプリを起動

We suggest that you begin by typing:

  cd my-app
  npm run dev

本書では開発を行うので最初に表示されているnpm run devコマンドを実行します。


 % cd my-app
 % npm run dev

> my-app@0.1.0 dev /Users/mac/Desktop/my-app
> next dev

ready - started server on http://localhost:3000
event - compiled successfully
event - build page: /next/dist/pages/_error
wait  - compiling...
event - compiled successfully
event - build page: /
wait  - compiling...
event - compiled successfully

localhost:3000にアクセスすると下記の画面が表示されます。これでNext.jsのインストールは完了です。

next.jsのデフォルトページ
next.jsのデフォルトページ

Hello Next.js

ディレクトリ構成

ディレクトリ構成の確認を行います。エディターはVisual Studio Codeを利用しています。ディレクトリはpages, styles, node_modules, publicの4つです。その他にREADME.mdとpackage.jsonとpackage-lock.jsonの3つのファイルがそ存在します。

ブラウザで表示されたページの内容はpagesディレクトリの中のindex.jsファイルに記述されています。このフォルダの中にアプリケーションのコアとなるコードを記述していくことになります。

Next.jsディレクトリ構成
Next.jsディレクトリ構成

publicディレクトリの中には、favicon.ico, vercel.svgファイルが保存されています。これらのファイルはブラウザから直接アクセスすることができます。

URLのlocalhost:3000の後ろに/vercel.svgを追加してください。publicディレクトリに保存したファイルには直接ブラウザからアクセスできることが確認できました。publicには静的なファイルを保存できることがわかります。例えばabout.htmlファイルをpublicフォルダに作成してもブラウザから直接アクセスでき、その内容を表示させることが可能です。

publicフォルダのファイルへのアクセス
publicフォルダのファイルへのアクセス

stylesディレクトリの下にはCSSのファイルを保存します。しかし、CSSファイルについてはpublicディレクトリに作成してJavaScriptのバンドルとしてではなく直接アクセスすることも可能です。

index.jsファイルの更新

index.jsファイルを更新するとブラウザ上に表示される内容も変更されるのか確認を行います。

index.jsの中身を一度削除して下記のように更新します。


export default function Home() {
  return <h1>Hello Next.js</h1>;
}
Reactの場合はファイル上部でimport React from ‘react’を記述しますが、Next.jsでは必要ありません。

npm dev runを実行していれば、index.jsを更新するとブラウザには自動で更新内容が反映されます。

Hello Next.js
Hello Next.js

ページのソースを確認してみましょう。ブラウザで右クリックして、ページのソースを表示してください。(Chromeの場合)

ソースの確認を行う
ソースの確認を行う

ソースの中にHello Next.jsファイルが入っていることがわかります。index.jsはJavaScriptファイルなのでJavaScriptファイルをブラウザが受け取って表示するのではなくブラウザが直接HTMLの情報を受け取っていることがわかります。これはNext.jsがブラウザに送信する前にpre-Renderingを行っていからです。HTMLの情報をそのまま受け取っているのでブラウザ側でのJavaScriptの処理を行う必要がありません。

これだけの情報ではpre-Renderingが行われているかはわかりません。Reactと比較してみましょう。

同じようにReactもh1タグでHello Reactと記述します。下の画像は字が細かすぎて見えないかもしれませんが、どこにもh1タグは表示されていません。つまりブラウザは受信したJavaScriptファイルを利用してh1タグを描写していることがわかります。

Reactnのソースを見る
Reactのソースを見る

ブラウザのソースを見るとことでClient RenderingとServer-side Renderingの違いも理解することができました。

別のページを作成する(静的ファイル)

Next.jsではpagesディレクトリにファイルを作成するだけで自動でルーティングが設定されるため簡単に静的ページを作成することができます。

pagesディレクトリの下にabout.jsファイルを作成します。index.jsと同様に下記のコードを記述します。h1タグの中身と関数名のみ変更しています。


export default function About() {
  return <h1>About Page</h1>;
}

URL:localhost:3000/aboutページにアクセスするとAbout Pageが表示されます。Next.jsを利用するとルーティングの設定を行うことなく簡単にページが作成できることが確認できます。

About.jsページを表示
About.jsページを表示

ここまでの設定では”/”(ルート)と/aboutページ以外にアクセスを行うと404エラーが表示されます。

404ページ
404ページ
404ページは存在しないページにアクセスした場合に表示されるエラーです。

pagesディレクトリ内にディレクトリを作成しその下にjsファイルを作成した場合の動作も確認しておきます。

まずpagesの下にproductsディレクトリを作成し、bag.jsファイルを作成します。


export default function Bag() {
  return <h1>バックのページです</h1>;
}

想像はつくとは思いますが、localhost:3000/products/bagにアクセスするとbag.jsファイルの中身が表示されます。ページの階層化も行うことができます。

bag.jsファイルの内容を表示
bag.jsファイルの内容を表示

動的ファイルの作成(ダイナミックルーティング)

productsの下にはbag以外にもさまざまな商品があるとします。ダイナミックルーティングを利用してURLのproduct/の次にどんな文字列を入れてもブラウザにファイルの内容が表示されるように設定を行います。

productsディレクトリの下にスクエアブラケットで囲まれた[name].jsファイルを作成します。


export default function Name() {
  return <h1>商品のページです</h1>;
}

/products/bagでもアクセスすることが可能ですが、bagをclothesやshoesに変更しても同じ内容が表示されます。

Dynamicルーティング
Dynamic Routing

しかしURLをbagやshoesに変更しても同じ”商品のページです”が表示されます。URLに入れた文字列をページ内容に表示させることでページの内容を動的に変更させるためuseRouterを利用します。

useRouterはnext/routerからimportします。


import { useRouter } from "next/router";
export default function Name() {
  const router = useRouter();
  return <h1>商品{router.query.name}のページです</h1>;
}

URLに含まれる文字列はrouter.query.nameから取得することができます。

ブラウザで確認するとURLに含まれる文字列を表示することができました。

URLに含まれる文字列を表示
URLに含まれる文字列を表示

console.logを利用してrouter.queryに含まれる情報を確認します。


import { useRouter } from "next/router";
export default function Name() {
  const router = useRouter();
  console.log(router.query);
  return <h1>商品{router.query.name}のページです</h1>;
}

デベロッパーツールで確認すると下記のようにオブジェクトの中にnameが含まれていることがわかります。


{name: "shoes"}
name: "shoes"
__proto__: Object

またURLにパラメータをつけてもrouter.queryから追加したパラメータの値を取得することが可能です。

URLにはhttp://localhost:3000/products/shoes?color=redのようにcolorのパラメータと値を設定しています。

パラメータを付与
パラメータを付与

リンクの設定

index.js, about.jsとproducts の下に[name].jsファイルを作成しましたが、リンクを設定していないのでブラウザのURLを手動で書き換える以外にページを遷移する方法がありません。ページ遷移ができるようにLinkの設定を行います。

index.jsが表示されるルートページからaboutページへの遷移を行うためLinkを利用します。Linkはnext/linkからインポートします。Linkタグの中で遷移したいページをhrefで設定します。


import Link from "next/link";
export default function Home() {
  return (
    <div>
      <ul>
        <li>
          <Link href="/about">
            <a>About</a>
          </Link>
        </li>
      </ul>
      <h1>Hello Next.js</h1>
    </div>
  );
}
About文字列にaタグがついていますが、もしclassを設定する場合はLinkタグではなくaタグにclassName属性を利用して設定を行います。

ブラウザで確認するとトップページからaboutページに遷移する際にページのリロードは行われずスムーズに画面が表示されます。

Linkタグを利用したページ遷移
Linkタグを利用したページ遷移

もしLinkタグではなくこれまどのHTMLのようにaタグを利用して設定を行ってみてください。ページの遷移を行うことができますがページを遷移する際にページのリロードが行われページが表示されるまでに時間がかかります。

遷移先の情報の入った配列を利用してダイナミックルーティングを行いたい場合も下記のように設定をすることでページのリロードなしにページ遷移することができます。


import Link from "next/link";
const products = [{ name: "bag" }, { name: "shoes" }, { name: "socks" }];
export default function Home() {
  return (
    <div>
      <ul>
        {products.map((product) => {
          return (
            <li>
              <Link as={`/products/${product.name}`} href="/products/[name]">
                <a>{product.name}</a>
              </Link>
            </li>
          );
        })}
        <li>
          <Link href="/about">
            <a>About</a>
          </Link>
        </li>
      </ul>
      <h1>Hello Next.js</h1>
    </div>
  );
}

リストの項目をクリックするとページが遷移します。

複数のページへのLink設定
複数のページへのLink設定

外部からデータを取得

外部から取得したデータを利用してブラウザに表示します。JSONPlaceholderを利用させてもらいます。

JSONPlaceholderを利用するとhttps://jsonplaceholder.typicode.com/postsにアクセスするだけで100件のPOSTS(投稿)データを取得することができます。また個別のPOST(投稿)データにアクセスしたい場合はURLのpostsの後ろにID番号を入れることでアクセスすることができます(posts/1, posts/2,…)。

Next.jsではサーバ側でデータを取得する方法がいくつか存在し、ここでは一般的に利用される2つの方法を確認します。

  • getStaticProps(Static Generation)
  • getServerSideProps(Server-side Rendering)

getStaticPropsはStatic Generationでビルド時に一度だけデータを取得して事前にページをpre-Renderingします。getServerSidePropsはServer-side Renderingでクライアントからのアクセス時にサーバ側でデータを取得しpre-Renderingします。

ブログの記事のようにクライアント側での更新がないものページにはgetStaticPropsを利用します。更新が行われるページにはgetServerSidePropsを利用します。getStaticPropsはビルド時にページが準備されているのですぐにページが表示されます。サイト、アプリケーションの高速化を実現するためにこの2つをうまく活用していく必要があります。

getServerSidePropsを利用した方法

getServerSidePropsを利用してデータを取得しページに表示させるために新たにpostsディレクトリを作成してindex.jsファイルを作成します。

作成したindex.jsファイルではgetServerSidePropsの中でJSONPlaceholderからfetchを利用してデータの取得を行っています。まずは正しくデータの取得ができているか確認するためにconsole.logを利用します。


export default function index({ posts }) {
  return (
    <div>
      <h1>POST一覧</h1>
    </div>
  );
}

export async function getServerSideProps() {
  const res = await fetch(`https://jsonplaceholder.typicode.com/posts`);
  const posts = await res.json();
  console.log(posts);
  return { props: { posts } };
}

通常であればコード中にconsole.logを記述するとブラウザのデベロッパーツールのコンソールログに情報が出力されます。しかし、getServerSidePropsはサーバ側(Next.js)で実行されるため、npm run devを実行したターミナルにpostsの100件分のデータが表示されることが確認できます。

getServerSidePropsは名前の通り、ServerSide(サーバーサイド)で実行されるメソッドです。リクエスト毎に実行されます。

データが取得できることが確認できたのであとはindex関数に渡したpropsをmap関数で展開します。


export default function index({ posts }) {
  return (
    <div>
      <h1>POST一覧</h1>
      <ul>
        {posts.map((post) => {
          return <li key={post.id}>{post.title}</li>;
        })}
      </ul>
    </div>
  );
}

export async function getServerSideProps() {
  const res = await fetch(`https://jsonplaceholder.typicode.com/posts`);
  const posts = await res.json();
  console.log(posts);
  return { props: { posts } };
}

ブラウザで確認するとgetServerSidePropsを利用して取得したデータがブラウザ上に表示されます。

POST一覧が表示
POST一覧が表示

個別ページの作成と表示

次は、取得後に展開したデータとダイナミックルーティングを使って個別のPOSTデータをどのように取得し表示させるのかを確認していきましょう。

ダイナミックルーティングに対応できるようにpostsの下に[post].jsファイルを作成します。


export default function post() {
  return <h1>POST(投稿)</h1>;
}

LinkをimportしてタイトルをクリックするとPOSTページに遷移するようにコードの更新を行います。


import Link from "next/link";
export default function index({ posts }) {
  return (
    <div>
      <h1>POST一覧</h1>
      <ul>
        {posts.map((post) => {
          return (
            <li key={post.id}>
              <Link href={`/posts/${post.id}`}>
                <a>{post.title}</a>
              </Link>
            </li>
          );
        })}
      </ul>
    </div>
  );
}

POST一覧画面に表示されているタイトルをクリックするとPOSTのページにページの再読み込みを行うことなくページ遷移するか確認を行ってください。ページ遷移後は以下の画面が表示されます。

POSTの個別ページ
POSTの個別ページ

POSTのidの取得

ページを遷移した時に個別ページの内容を表示させるためには、postのIDを取得して再度JSONPlaceholderにアクセスを行い、個別ページの情報を取得する必要があります。

postのIDはgetServerSidePropsのparamsを通して取得することができます。postのIDが取得できるのかどうかconsole.logを利用して確認します。


export async function getServerSideProps({ params }) {
  console.log(params);
  const res = await fetch(`https://jsonplaceholder.typicode.com/posts`);
  const posts = await res.json();
  return { props: { posts } };
}

POSTの一覧から個別ページにアクセスするとnpm run devを実行したターミナルにオブジェクトとして表示されます。


{ post: '1' }

ダイナミックルーティングを利用しているためでIDの値をparamsで取得しましたが、params以外にもreq, res, queryといった値も取得することができます。それらの情報を確認してみたい場合は、getServerSidePropsの引数にcontextを入れてconsole.log(context)で確認してください。reqはrequestの略でアクセスしたきたクライアント情報やヘッダー情報も確認することができます。

個別ページのデータ取得

paramsに保存されたIDを利用して個別データの取得を行います。


export default function post({ post }) {
  return (
    <div>
      <h1>POST(投稿){post.id}</h1>
      <h2>{post.title}</h2>
      <p>{post.body}</p>
    </div>
  );
}

export async function getServerSideProps({ params }) {
  const id = params.post;
  const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`);
  const post = await res.json();
  return { props: { post } };
}

ブラウザで確認すると下記のように個別のPOSTデータの内容を表示させることができます。

個別のPOSTデータの取得
個別のPOSTデータの取得

getStaticPropsを利用した方法

getServerSidePropsはリクエスト毎にサーバ側でデータの取得が行われますががgetStaticPropsはビルド時にデータの取得を行います。

getStaticPropsへの変更

POSTSの一覧を取得するためにpostsディレクトリのindex.jsファイルのgetServerSidePropsをgetStaticPropsに変更を行います。


export async function getStaticProps() {
  const res = await fetch(`https://jsonplaceholder.typicode.com/posts`);
  const posts = await res.json();
  return { props: { posts } };
}

メソッドを変更しただけではブラウザ上では何も変化がなくPOST一覧が取得できます。

POST一覧が表示
POST一覧が表示

次に[post].jsファイルでもgetServerSidePropsからgetStaticPropsに変更を行います。


export async function getStaticProps({ params }) {
  const id = params.post;
  const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`);
  const post = await res.json();
  return { props: { post } };
}

index.jsの場合はgetServerSidePropsからgetStaticPropsに変更するだけで同じようにデータが表示されましたが、[post].jsファイルではエラーが表示されます。

エラーの内容はgetStaticPathsがダイナミックSSG(ServerSide Static Generatoin)ページでは必要と記述されています。

エラー:getStaticPathsが必要
エラー:getStaticPathsが必要

getStaticPathsによるパス情報の取得

getStaticPathsメソッドの追加を行います。getStaticPathsメソッドの中ではpostsの一覧を取得しその中からpostsの個別ページのパス(/posts/${post.id})を取り出しています。getStaticPathsのメソッドの中ではビルド時に作成するページのパス一覧を作成して、pathsでreturnする必要があります。getStaticPathsは作成するページのパス情報を渡す役割をもっているため、getStaticPathsがない場合はパス情報がないため、先ほどのようなエラーが発生します。


export async function getStaticPaths() {
  const res = await fetch(`https://jsonplaceholder.typicode.com/posts`);
  const posts = await res.json();
  const paths = posts.map((post) => `/posts/${post.id}`);
  return {
    paths,
    fallback: false,
  };
}

getStaticPathsで個別ページのパス情報が取得できると個別ページにアクセスしてもエラーなしでページが表示されます。

fallbackの設定

fallbackはtrueとfalseを設定することができ、falseに設定した場合は存在するPostのページ以外にアクセスした場合に404エラーが表示されます。下記は存在しない101にアクセスを行っています。

fallbackの値がfalseの場合
fallbackの値がfalseの場合

fallbackをtureに設定した場合はサーバエラーの画面が表示されます。ビルド時に存在しなかったページが追加された場合にtureを設定しておくことでそのページにアクセスするとページのビルドが行われ作成されたページをユーザに返すことができます。

fallbackをtrueに設定した場合
fallbackをtrueに設定した場合

styled-jsxによるCSSの適用

styled-JSXを利用してCSSの適用を行っていきます。CSSを適用する方法は複数ありstyled-JSXを利用する必要はありません。

好き嫌いの好みのが別れそうですがJavaScriptの関数の中にCSSを記述することができます。見慣れるまでには不自然に感じてしまうかもしれませんが、特別難しいことはありません。早速使用方法を確認してみます。

h1タグの文字色、背景色を変更したい場合は下記のように記述することができます。


export default function Home() {
  return (
    <div>
      <h1>Hello Next.js</h1>
      <style jsx>
        {`
          h1 {
            color: red;
            background: green;
          }
        `}
      </style>
    </div>
  );
}

styleタグの中に{“}を入れるのを忘れてないでください。それ以外は通常のCSSファイルと同様にCSSを記述することができます。

styled-cssの適用方法
styled-cssの適用方法

classNameを利用した適用方法

classを使って適用する場合はclassNameを利用する必要があります。classNameを利用するのはstyled-jsxを利用するときだけに限定されるものではなくJSX内でclassを利用するために使われます。


export default function Home() {
  return (
    <div>
      <h1 className="heading">Hello Next.js</h1>
      <style>
        {`
          .heading {
            color: red;
            background: green;
          }
        `}
      </style>
    </div>
  );
}

Component内での適用について

index.jsファイル内に関数を使ってContentコンポーネントを作成します。Contentコンポーネント内にstyled-jsxを利用してCSSを適用します。


function Content() {
  return (
    <div>
      <p>ここにコンテンツが入ります。</p>
      <style jsx>{`
        p {
          color: blue;
        }
      `}</style>
    </div>
  );
}

ContentコンポーネントではpタグにCSSを適用しているので親側のHomeコンポーネントにもpタグを追加し、適用範囲を確認します。


export default function Home() {
  return (
    <div>
      <h1 className="heading">Hello Next.js</h1>
      <Content />
      <p>ここにもコンテンツが入ります。</p>
      <style>
        {`
          .heading {
            color: red;
            background: green;
          }
        `}
      </style>
    </div>
  );
}

ブラウザで確認した結果、styled-jsxで適用したCSSはContentコンポーネント内のpタグのみに適用されることがわかります。

Contentコンポーネント内のみの適用
Contentコンポーネント内のみの適用

Contentコンポーネント内のみにCSSを適用できるため他のコンポーネントに影響を与えません。そのため作成したコンポーネントを再利用を効率的に行うことができます。もしコンポーネントの外に影響がある場合はCSSの上書きやクラス名の重複などを心配する必要があります。

もしコンポーネント外にstyled-cssで設定したCSSを適用したい場合はglobalをstyleタグに追加することで適用できます。


function Content() {
  return (
    <div>
      <p>ここにコンテンツが入ります。</p>
      <style global jsx>{`
        p {
          color: blue;
        }
      `}</style>
    </div>
  );
}

Cotentコンポーネント外のpタグにもCSSが適用されていることが確認できます。

styleタグにglobalを追加
styleタグにglobalを追加

styled-jsx内で変数を利用

styled-jsxはJSXの中つまりJavaScriptの中に記述しているので変数や関数を利用することも可能です。Contentコンポーネントが親コンポーネントから受け取ったpropsの値を利用して動的に適用するCSSを変更することができます。

propsで受け取ったtypeの文字列がalertであれば文字色は赤、alertでない文字列の場合は青になるように設定しています。

function Content({ type }) { return ( <div> <p>ここにコンテンツが入ります。</p> <style global jsx>{` p { color: ${type == “alert” ? “red” : “blue”}; } `}</style> </div> ); }

<Content type="alert" />

alertを渡すと文字は赤になっています。

propsのtypeでalertを渡す
propsのtypeでalertを渡す

<Content type="warning" />

alert以外を渡すと文字は青になっています。

propsのtypeでwariningを渡す
propsのtypeでwariningを渡す

CSSファイルによるCSSの適用

先ほど述べたようにCSSの適用にはさまざまな方法で行うことができます。stylesディレクトリにあるglobals.cssを利用しても適用することができます。

global.css以外の任意の名前をつけることは可能です。

globals.cssファイルはnext.jsのインストール時から存在する.app.jsファイルの中でimportが行われています。

stylesディレクトリに下に保存されているglobals.cssファイルを開いて.headingを追加します。


.heading {
  color: green;
}

index.jsのh1タグにはheadingクラスが設定されています。


export default function Home() {
  return (
    <div>
      <h1 className="heading">Hello Next.js</h1>
    </div>
  );
}

ブラウザで確認するとglobals.cssに記述したheadingが適用されていることが確認できます。

global.cssファイルによる適用
global.cssファイルによる適用

_app.jsではなくindex.jsファイルでglobals.cssファイルをimportするとエラーが発生します。Global CSS cannot be imported from files other than your Custom . Please move all global CSS imports to pages/_app.tsx….

ではコンポーネントにCSSファイルを使ってCSSを適用したい場合はどのように行うのでしょうか。適用方法について確認を行っていきます。

module.cssファイルによりCSSの適用

stylesディレクトリの下にはNext.jsをインストール後、2つのファイルが保存されています。一つがglobals.cssでもう一つがHome.module.cssです。cssの拡張子の前にmoduleが入っているのがポイントです。

globals.cssが_app.jsからimportしてアプリケーション全体に記述したCSSを適用することができます。XXXX.module.cssファイルはコンポーネントでimportを行うことがファイルです。しかし、importの方法が異なります。


import styles from "../styles/Home.module.css";

適用方法も下記のように行います。

import styles from “../styles/Home.module.css”; export default function Home() { return ( <div> <h1 className={styles.heading}>Hello Next.js</h1> </div> ); }

Home.module.cssファイルは下記のように記述しています。


.heading {
  background-color: red;
}
CSSが適用された画面です。
CSSが適用された画面です。

まとめ

外部からのデータの取得方法まで確認を行うことができたので、ブログの記事データなどfetchコマンドで取得することが可能であればここまでの知識でブログサイトの作成も行うことが可能です。しかしSEOのためメタタグの設定等が必要になるため、さらに学習が必要となります。今後本ブログでも設定方法を紹介していきます。