React × Next.js 実践開発入門 #5 Next.jsでアセット、メタデータ、CSSを扱う
この講座はYouTubeで動画形式でも用意しています。合わせてご覧ください。
はじめに
前回は、Next.jsでのページ遷移の方法について学びました。今回は、次の内容について学びましょう。
また、最後により良いレイアウトの実践的な方法や、スタイリングのTipsも紹介します。
アセット
Webサイトを作る際には、画像やfavicon(ページのアイコン)などの素材が必要になります。これらをアセットといい、Next.jsがルート直下に用意するpublicというディレクトリの中にファイルを置いていきます。これらをアプリケーションの中から呼び出します。
例えば、Next.jsのプロジェクトを作った時点では、次のようにvercel.svgという画像ファイルを呼び出しています。
<img src="/vercel.svg" alt="Vercel Logo" className="logo" />
このvercel.svgは、publicディレクトリ内に配置されています。
メタデータ
メタデータとは、HTMLでheadタグ内に書かれるような情報で、ブラウザのページ表示領域に直接現れないような情報を指します。例えば次のようなものがあります。
- ページタイトル
- OGP (SNSやチャットでURLがシェアされた際に表示されるタイトルやサムネイルなどの設定)
Next.jsにはHeadコンポーネントが用意されています。次のようにインポートします。
import Head from 'next/head';
メタデータを制御したいページのコンポーネントで、Headコンポーネントを用います。
export default function Home() {
return (
<div>
<Head>
<title>Create Next App</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<main> ... </main>
</div>
)
}
それぞれのページコンポーネントにHeadコンポーネント用いることで、ページごとに異なるタイトルも設定できます。
export default function FirstPost() {
return (
<>
<Head>
<title>First Post</title>
</Head>
...
</>
)
}
レイアウトコンポーネント
続いては、レイアウトコンポーネントを学びます。Next.jsに限らず、共通コンポーネントを作成して複数箇所で再利用すると言う手法はよく使われます。
レイアウトコンポーネントの具体例を見てみましょう。ページを作成する際はpages
ディレクトリにファイルを作成しましたが、今回はcomponents
ディレクトリにLayout.tsx
ファイルを作成します。
import React from 'react';
const Layout: React.FC = ({ children }) => <div>{children}</div>
渡されたchildren
をdiv要素で括るだけのレイアウトコンポーネントが作成できました。このLayoutコンポーネントは、他のページコンポーネントなどで利用できます。
利用する際は、まずインポートが必要です。
import Layout from '@/components/Layout';
export default function FirstPost() {
return (
<Layout>
<Head>...<Head>
<h1>First Post</h1>
...
</Layout>
)
}
というように利用できます。この時点では、Layoutコンポーネントによって、ただdiv要素で括られているだけです。
CSSスタイリング
続いては、CSSによってページスタイルを指定する方法を学びます。Next.jsではいくつかCSSスタイリングの方法があります。主なものは次の通りです。
- styled-jsx (デフォルトで利用可能)
- CSS Modules (デフォルトで利用可能)
- styled-components (利用には設定が必要)
- emotion (利用には設定が必要)
まずはstyled-jsxを見ていきましょう。CSS Modulesは後述します。
styled-jsx
https://github.com/vercel/styled-jsx
styled-jsxは、コンポーネント内にCSSを書く方法です。<style jsx>
〜</style>
という形式で記述します。通常のCSSの書き方に近い方法です。この方法を用いると、コンポーネント内で閉じたスタイルになるため、他のコンポーネントに影響しないようにできます。
CSS Modules
https://github.com/css-modules/css-modules
CSS Modulesを用いて、共通コンポーネントにスタイルを当てていきます。こうすることで、共通コンポーネントが使われているすべての箇所で同じスタイルを適用できます。
先ほどはcomponents/Layout.tsx
というファイルにレイアウトコンポーネントを作成しました。同じ階層にCSSファイルを作成しましょう。components/Layout.module.css
ファイルを作成し、通常と同じようにCSSを記述します。
.container {
max-width: 36rem;
padding: 0 1rem;
margin: 3rem auto 6rem;
}
このスタイルを利用しましょう。CSS Modulesもimport文で読み込ませることができます。Layout.tsx
に追記します。
import styles from './Layout.module.css';
スタイルを当てる際には、先ほどのCSSファイルに記述したクラス名を用いて次のように記述します。
const Layout: React.FC = ({ children }) => (
return <div className={styles.container}>{children}</div>
)
CSS Modulesを利用すると、CSSファイルをJSファイルから分離できるというメリットがあります。
グローバルCSS
コンポーネントごとに閉じたスタイルを当てることは非常に便利ですが、ページ全体に適用させたいスタイルもあります。こうしたスタイルはグローバルCSSと呼ばれル方法によって指定できます。
Next.jsでグローバルCSSを使う際は、_app.tsx
という特別な名前のファイルを作成してコンポーネントを記述します。このコンポーネントは、Next.jsの全てのページコンポーネントに共通で用いられます。
import { AppProps } from 'next/app'
import '@styles/global.css'
export default App({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
}
この2行目の部分がグローバルCSSをインポートしている部分です。通常のCSSファイルを作成してimport文でインポートすることによってページ全体に適用させるスタイルを指定できます。
より良いレイアウトの実践的な方法
ここまで、共通レイアウトやグローバルCSSについて学びました。より良いレイアウトをする方法を学びましょう。
三項演算子による表示切り替え
例えば、ホームページかどうかでヘッダーの表示を切り替えたいとします。home
という変数に応じて表示コンテンツを変えるには、三項演算子を用いた分岐を用います。
<header>
{home ? (
<> ... </>
) : (
<> ... </>
)}
</header>
Propsを用いた値渡し
共通コンポーネントとして利用する際にhome
をPropsを用いて受け取りたいので、Propsの型を定義します。?
は省略可能を表します。
type Props = {home?: boolean}
const Layout = React.FC<Props> = ({ children, home }) => {
...
}
このLayoutコンポーネントを利用してみましょう。FirstPostページは一般のページなので単に<Layout>
で括ります。
export default function FirstPost() {
return (
<Layout>
<Head>
<title>First Post</title>
</Head>
<h1>First Post</h1>
...
</Layout>
)
}
Homeページコンポーネントでは、home
というPropsを渡します。
export default function Home() {
return (
<Layout home>
<Head>
<title>{siteTitle}</title>
</Head>
<section>...</section>
</Layout>
)
}
コンポーネント以外の共通利用
コンポーネント以外にも共通で利用するものは、ファイルを分割してインポートによる利用ができます。
例えばHomeコンポーネントで見たsiteTitleは、Home.tsx
内で定義しても良いですが、これをLayout.tsx
に移してみましょう。
export const siteTitle = 'Next.js Sample Website'
Home.tsx
ではimport
文によって利用します。
import Layout, { siteTitle } from '@/components/siteTitle'
このLayoutコンポーネントの全体像は、以下を参照してください。他にも今までに学んだ技術を利用しています。
<Head>
コンポーネントによるメタデータを追加<Link>
コンポーネントによるページ遷移- CSS Modulesによるスタイリング
https://github.com/redimpulz/nextjs-react-training-blog/blob/master/components/Layout.tsx
スタイリングのTips
classnamesによるスタイル切り替え
classnamesは条件によってスタイルを切り替えたい場合に有用なライブラリです。
まずはスタイル適用前の状態のAlert
という名前のコンポーネントを作成します。このコンポーネントはtype
というPropsを受け取るので、Propsの型定義を含めて次のように書けます。
import React from 'react';
import styles from './alert.module.css';
type Props = { type: 'success' | 'error' };
const Alert: React.FC<Props> = ({ children, type }) => {
return (
<div>
{children}
</div>
);
};
export default Alert;
TypeScriptでは、単に文字列を表すにはtype: string
と記述すれば良いのですが、今回はtype: 'success' | 'error'
と記述することで2通りの文字列に限定しています。
さて、classnamesを利用しましょう。classnamesは引数の右側に渡したオブジェクトの右側(値)に条件式を渡すことでtrue
であれば左側(キー)のスタイルを適用させることができます。
まずはimport
文を追加します。
import cn from 'classnames';
Propsのtype
が'success'
であれば、CSSの.success
クラスのスタイルが適用されるように、また'error'
であっても同様に.error
が適用されるようにします。
const Alert: React.FC<Props> = ({ children, type }) => {
return (
<div
className={cn({
[styles.success]: type === 'success',
[styles.error]: type === 'error',
})}
>
{children}
</div>
);
};
PostCSSによるCSSの効率化
https://github.com/postcss/postcss
PostCSSは、設定を記述しておくことによって、設定に応じてCSSを自動で加工できます。LESSやSassと似たようなツールになります。
また、PostCSSを使ったCSSのツールがいくつかあり、その1つにtailwindcssがあります。
PostCSSを用いるにはいくつかのライブラリをインストールする必要があります。
npm install -D tailwindcss autoprefixer postcss
PostCSSの設定ファイルpostcss.config.js
を作成します。
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
tailwindcssの設定ファイルtailwind.config.js
も作成します。
module.exports = {
content: [
'./pages/**/*.{js,ts,jsx,tsx}',
'./components/**/*.{js,ts,jsx,tsx}',
],
};
準備が整えば、tailwindcssの記法を用いて、tailwindcssのスタイルが適用されたボタンを作成できます。
<button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Button
</button>
Sass
SassはCSSの構文を拡張し、より便利に記述できるようにしたものです。
yarn add sass
でインストールするだけで利用可能になります。あとはCSS Modulesの拡張子を、.css
から.scss
に変更するだけで利用できます。
まとめ
今回は、アセットやメタデータ、スタイリングを学習しました。
次回は事前レンダリングや静的生成、データ取得について学びます。