「Next.js + TypeScript」の導入・基盤作成・Scssの導入まで解説
こんにちは、okutani(@okutani_t)です。本記事では、Reactのフレームワークである「Next.js」の導入方法について解説しています。また、TypeScriptの導入も同時におこなっています。
Next.jsの概要はかんたんに以下のとおりです。
- Reactを利用している
- SSR(サーバーサイドレンダリング)、 SSG(スタティックサイトジェネレーション)ができる
- Vercel, Incが開発をおこなっている
上記とてもざっくりと解説しているので、Next.jsで何ができるか詳しく知りたい方は別途調べてみてください。
また、Nuxt.jsというVue.js製のフレームワークもありますが、そちらは別物です。勘違いしないように注意しましょう。
本記事で扱うツールのバージョンはそれぞれ以下のとおりです。
- React:17.0.2
- Next.js:10.2.2
- TypeScript: 4.0.7
Next.jsの公式サイトは以下です。
LINKNext.js by Vercel – The React Framework
また、本記事で解説しているサンプルアプリの実装は、Next.jsの「Getting Started」ページを参考にしています。合わせてご覧ください。
また、今回サンプルで作成したプロジェクトは以下のGitHubリポジトリから確認することができます。
LINKokutani-t/first-nextjs-typescript-sample
それでは、Next.jsの導入方法から初期設定、サンプルアプリの実装まで見ていきましょう。
スポンサーリンク
もくじ
Next.jsの導入方法
以下のコマンドを実行して、Next.js + TypeScriptのプロジェクトを作成します。今回はすでにTypeScriptが導入されているテンプレート「with-typescript」を利用します。
$ mkdir myapp
$ cd myapp
$ npx create-next-app --example with-typescript .
「create-react-app」が導入されていない場合は、以下のように聞かれるのでyキー、Enterキーを入力。
Need to install the following packages:
create-react-app
Ok to proceed? (y)
これでNext.js + TypeScriptのプロジェクトが作成されました。
もしくは、直接プロジェクト名を指定して導入することもできます。
$ npx create-next-app --example with-typescript myapp
他にもTypeScriptの導入方法はいくつかありますが、今回はwith-typescriptのテンプレートを利用するのがお手軽かつ分かりやすいので、本記事ではwith-typescriptを利用しています。詳しく知りたい方は以下のリンクを確認してみてください。
LINKnext.js/examples/with-typescript at canary · vercel/next.js
確認
以下のコマンドを実行してサーバーを起動させます。
$ yarn dev
// もしくは
$ npm run dev
ブラウザで「localhost:3000」へアクセス。以下の画面が表示されればOKです。
最初からいくつかコンテンツが表示されているのが確認できます。
次に、サイトの初期設定(基盤づくり)をおこなっていきます。
基盤作成
一般的なWebサイトを想定して初期設定をおこなっていきます。かつNext.jsの基本構造を確認していきましょう。
不要なファイルを削除
今回利用するテンプレート「with-typescript」は最初からいくつかのファイルを生成しています。
そのまま利用してもいいですが、不要だと思ったファイルは削除していきましょう。今回は以下のファイルをすべて削除しました。また、削除したファイルもどのような構成になっているか中身を確認しながら削除していくと勉強になると思います。
- components/List.tsx
- components/ListDetail.tsx
- components/ListItem.tsx
- pages/api/
- pages/users/
- pages/about.tsx
- utils/sample-data.ts
- interfaces/index.ts(今回は中身だけ削除)
「interfaces/index.ts」は今後利用するかもしれないので、とりあえず中身のコードだけ削除して、index.tsファイル自体は残しておきました。
また、「pages/about.tsx」はそのまま下層ページとして動作するので、検証用に残しておいても良いかと思います。
最低限のコンテンツを表示してみる
削除したファイルに合わせてファイルを書き換えてみます。以下の通り書き換えてみました。
- pages/index.tsx
import Layout from '../components/Layout'
const IndexPage = () => (
<Layout title="Home | Next.js + TypeScript Example">
<h1>Next.js + TypeScriptのテスト</h1>
<p>
Next.js + TypeScriptのテストプロジェクトです。
</p>
</Layout>
)
export default IndexPage
- components/Layout.tsx
import React, { ReactNode } from 'react'
import Link from 'next/link'
import Head from 'next/head'
type Props = {
children?: ReactNode
title?: string
}
const Layout = ({ children, title = 'Next.js + TypeScriptのサンプルサイト' }: Props) => (
<div>
<Head>
<title>{title}</title>
<meta charSet="utf-8" />
<meta name="viewport" content="initial-scale=1.0, width=device-width" />
</Head>
<header>
<nav>
<Link href="/">
<a>Home</a>
</Link>
</nav>
</header>
{children}
<footer>
<hr />
<span>© 2021 Next.js + TypeScript Sample</span>
</footer>
</div>
)
export default Layout
変更を保存してサイトを確認してみます。
不要なファイルを削除し、最低限のコンテンツを表示できました。
さらに基盤を作成していきましょう。
基盤ファイルの追加
以下のファイルをそれぞれ作成していきます。
pages/_app.tsx
「pages/_app.tsx」を設置することで、全ページで読み込ませたいファイル(Layout.tsxやcssなど)を管理することができます。
- pages/_app.tsx
import { AppProps } from "next/app"
import Layout from "../components/Layout"
const App = ({ Component, pageProps }: AppProps) => {
return (
<>
<Layout>
<Component {...pageProps} />
</Layout>
</>
)
}
export default App
こうすることで全ページで共有したLayoutを読み込むことができます。「pages/index.tsx」も合わせて編集しておきます。
- pages/index.tsx
const IndexPage = () => (
<>
<h1>Next.js + TypeScriptのテスト</h1>
<p>
Next.js + TypeScriptのテストプロジェクトです。
</p>
</>
)
export default IndexPage
これで新しいページを追加するときにLayoutを個別で設定しなくてもよくなりました。
pages/_document.tsx
次に「pages/_document.tsx」を追加して、htmlタグやbodyタグの拡張をおこなえるようにしておきます。以下のように設定しました。
- pages/_document.tsx
import NextDocument, { Html, Main, Head, NextScript } from 'next/document'
type Props = {}
class Document extends NextDocument<Props> {
render() {
return (
<Html lang='ja'>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default Document
これで先ほどと同じように表示されるか確認してみましょう。また、ブラウザの検証機能でhtmlタグに「lang=’ja’」が設定されているか確認してみてください。
meta情報を設定
次に、metaタグまわりの設定をおこないます。
「components/Meta.tsx」を作成し、以下のように設定。
- components/Meta.tsx
import React from 'react'
import Head from 'next/head'
type Props = {
title: string
description: string
url: string
}
const Meta = ({ title, description, url }: Props): JSX.Element => {
return (
<Head>
<title>{title}</title>
<meta charSet='utf-8' />
<meta name='viewport' content='width=device-width, initial-scale=1, shrink-to-fit=no' />
<meta name='description' content={description} />
<meta name='keywords' content='' />
<meta property='og:title' content={title} />
<meta property='og:description' content={description} />
<meta property='og:type' content='website' />
<meta property='og:url' content={url} />
<meta property='og:image' content='https://サイトURL/images/ogp.png' />
<meta property='og:site_name' content={title} />
<meta property='og:locale' content='ja_JP' />
<meta name='twitter:card' content='summary_large_image' />
<meta name='twitter:site' content='' />
<link rel='canonical' href={url} />
<link rel='shortcut icon' href='/images/favicon.ico' />
<link rel='apple-touch-icon' type='image/png' href='/images/icon.png' sizes='180x180' />
<link rel="preconnect" href="https://fonts.gstatic.com" />
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap" rel="stylesheet" />
</Head>
)
}
export default Meta
上記は一例なので、各自自由に設定してみてください。Google FontsなどをCDNで読み込むときもこちらに記述すればOKです。
また、各画像ファイルは「public/images/」以下に配置すれば読み込みます。
次に「pages/index.tsx」を編集。
- pages/index.tsx
import Meta from '../components/Meta'
const IndexPage = () => (
<>
<Meta
title="Next.js + TypeScriptのテスト"
description="Next.js + TypeScriptのテストプロジェクトです。"
url="https://ここにURL"
/>
<h1>Next.js + TypeScriptのテスト</h1>
<p>
Next.js + TypeScriptのテストプロジェクトです。
</p>
</>
)
export default IndexPage
これでmeta情報を読み込むことができました。ブラウザを立ち上げて検証でheadタグ内にmetaタグがあることを確認してみてください。
ページを新たに追加したときも、同じように作成したMeta.tsxを読み込んで設定すればOKです。
また、「components/Layout.tsx」内のmeta周りの記述は不要になったので以下のように編集しておきました。
- components/Layout.tsx
import React, { ReactNode } from 'react'
import Link from 'next/link'
type Props = {
children?: ReactNode
}
const Layout = ({ children }: Props) => (
<>
<header>
<nav>
<Link href="/">
<a>Home</a>
</Link>
</nav>
</header>
{children}
<footer>
<hr />
<span>© 2021 Next.js + TypeScript Sample</span>
</footer>
</>
)
export default Layout
では最後に、Scssの導入について解説していきます。
Sass(Scss)の導入
Scssを利用するためにSassを導入します。
以下のコマンドを実行。
$ yarn add sass
# or
$ npm install sass
「next.config.js」を以下の内容で作成します。
- next.config.js
const path = require('path')
module.exports = {
sassOptions: {
includePaths: [path.join(__dirname, 'styles')],
},
}
これでSCSSが利用できるようになりました。
「styles/global.scss」を作成してみます。このファイルにはアプリケーション全体で読み込みたいCSSを記述します。
- styles/global.scss
body {
margin: 0 auto;
font-family: 'Noto Sans JP', sans-serif;
max-width: 500px;
color: #333;
background: #f8f8f8;
}
今回はかんたんなレイアウトと、meta情報の設定で読み込んだGoogle Fontsを利用してみました。
_app.tsxで読み込みます。
- pages/_app.tsx
import { AppProps } from 'next/app'
import Layout from '../components/Layout'
import '../styles/global.scss' // この行を追加
const App = ({ Component, pageProps }: AppProps) => {
return (
<>
<Layout>
<Component {...pageProps} />
</Layout>
</>
)
}
export default App
確認してみます。
レイアウトが変更されているのが確認できました。
今回はグローバルにCSSを読み込みましたが、CSS Modulesなどを適宜利用してもいいかと思います。
まとめ
今回はNext.js + TypeScriptの導入について解説しました。
meta情報、Scssの利用なども参考にしてください。
また、今回のサンプルアプリのソースコードはGitHubに公開しているので参考にしてください。
LINKokutani-t/first-nextjs-typescript-sample
Web開発のお仕事を募集しています
フリーランスのエンジニアとして、Webシステム開発のお仕事依頼を随時募集しています(現在の業務量によってお受けできない場合もあります)。
「Ruby on Rails」「JavaScript(jQuery, Reactなど)」「HTML + CSS」を用いたシステム開発、「Heroku」等を用いたサーバー構築・運用、「Git」や「GitHub」を利用したソーシャルコーディングなどに対応しています。
ご依頼を検討している方は、下記リンク本ブログからのお問い合わせ、もしくはokutaniのポートフォリオからご連絡ください。
LINKお問い合わせ
スポンサーリンク