Next.js --TypeScript をVercelでホスティングしてシンプルなブログを運営してみる。

本稿では、以下の技術スタックを使用してクライアントサイドのwebアプリケーションをホスティングしていきます。

| スタック | 役割
| - | - 
| Next.js | UI管理
| TypeScript | 開発体験向上
| Vercel | ホスティング

ひとまず、Next.jsを始める第一歩としてめちゃくちゃシンプルなものをVercelにアップロードしていきます。

### refferences

https://nextjs.org/

https://typescript-jp.gitbook.io/deep-dive/

https://tailwindcss.com/docs/guides/nextjs

https://vercel.com/

## まずはHello World on Vercel

まずはNext.jsアプリケーションを、ささっとVercelにデプロイしていきましょう。

早ければ10分かからずに完了しちゃいます。

```console
// アプリケーションを管理しているディレクトリに移動
$ cd code/

// Nextをnpxで作成
// 途中でいくつか質問されますが、基本デフォルト設定でOKです。
$ npx create-next-app@latest --typescript

// 先ほど作成したプロジェクトに移動
$ cd my-next-app

// ローカルで起動
$ npm run dev
```

http://localhost:3000/ で起動させられたら、以下のようなページが表示されます。

![スクリーンショット 2023-03-19 15.14.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684929/7c190c60-4ea5-23dd-4ec7-ec8c08ee3e4f.png)

ここまで確認できたら、Vercelにデプロイ。

https://vercel.com

サインアップがまだの場合はGithub連携等で登録を済ませ、ダッシュボードから

- Add New で新規プロジェクトを作成
- Githubリポジトリと接続してデプロイ

の手順を行ってください。

無事デプロイが完了すると、Vercelから発行される以下のようなURIで、ローカルで起動しているNextアプリと同じようなアプリケーションが表示されます。

`https://{your-pj-name}-kappa.vercel.app/`

一先ず、VercelでNext.jsアプリケーションを動かす事ができました。

[ref]

https://zenn.dev/msk1206/articles/dba565eb3985b4

### オプショナルな情報の確認

先ほど `npx create-next-app@latest --typescript` を入力した際に幾つか質問されましたが、あれについて詳しく見ていきましょう。

具体的には、以下のような質問がされました。

```console
$ npx create-next-app@latest --typescript
✔ What is your project named? … test-next
✔ Would you like to use ESLint with this project? … No / Yes
✔ Would you like to use `src/` directory with this project? … No / Yes
✔ Would you like to use experimental `app/` directory with this project? … No / Yes
? What import alias would you like configured? › @/*
```

この中で、以下2つの質問に関してはいまいち意味が分からないですよね。

```console
✔ Would you like to use `src/` directory with this project? … No / Yes
✔ Would you like to use experimental `app/` directory with this project? … No / Yes
```

これ、以下の3パターンでそれぞれ実際にプロジェクトをinitializeして、作成される初期プロジェクトの違いを確認してみました。

- srcとapp、どちらもNo
- srcのみYes
- srcとapp、どちらもYes

実際にプロジェクトを作成すると、以下のようなディレクトリ構成で初期化されます。

### srcとapp、どちらもNo

<details>

```console
$ tree -L 1
.
├── README.md
├── next-env.d.ts
├── next.config.js
├── node_modules
├── package-lock.json
├── package.json
├── pages
├── public
├── styles
└── tsconfig.json

5 directories, 6 files

$ tree pages/ -L 2
pages/
├── _app.tsx
├── _document.tsx
├── api
│   └── hello.ts
└── index.tsx

2 directories, 4 files
```

</details>

### srcのみYes

<details>

```console
$ tree -L 1       
.
├── README.md
├── next-env.d.ts
├── next.config.js
├── node_modules
├── package-lock.json
├── package.json
├── public
├── src
└── tsconfig.json

4 directories, 6 files

$ tree src/ -L 2
src/
├── pages
│   ├── _app.tsx
│   ├── _document.tsx
│   ├── api
│   └── index.tsx
└── styles
    ├── Home.module.css
    └── globals.css

4 directories, 5 files
```

</details>

### srcとapp、どちらもYes

<details>

```console
$ tree -L 1
.
├── README.md
├── next-env.d.ts
├── next.config.js
├── node_modules
├── package-lock.json
├── package.json
├── public
├── src
└── tsconfig.json

4 directories, 6 files

$ tree src/ -L 2
src/
└── app
    ├── api
    ├── favicon.ico
    ├── globals.css
    ├── layout.tsx
    ├── page.module.css
    └── page.tsx

3 directories, 5 files
```

</details>

### で、実際に何が違うのか

実際に何が違うのかですが、まずsrcディレクトリを作成した場合に関しては、純粋にpages/ディレクトリで使用していたコードを、src/ディレクトリで管理できるようになるという事のようです。

https://nextjs-ja-translation-docs.vercel.app/docs/advanced-features/src-directory

以下のNextの過去ポストから引用。

https://nextjs.org/blog/next-9-1#src-directory-support

> src directory support
Next.js has a special pages directory where every file becomes a separate route, following the convention over configuration approach this directory is required to be in the root of a Next.js application.
> 
> In talking with companies using Next.js and inspecting some closed source codebases we established a common pattern developers wanted is to have a src directory for their code and have the pages directory within it also.
> 
> Starting from Next.js 9.1, it's now possible to create a src/pages directory instead of creating a pages directory in the root of the application.
> 
> Using the src directory is optional and covers the case where your company has this standard in place already.


DeepLで翻訳

> Next.jsは、各ファイルが個別のルートになる特別なpagesディレクトリを持っています。このディレクトリは、設定よりも規約を重視するアプローチに従って、Next.jsアプリケーションのルートにあることが要求されます。
> 
> Next.jsを利用している企業やクローズドソースのコードベースを調査したところ、開発者が望む共通のパターンとして、コード用のsrcディレクトリを持ち、その中にpagesディレクトリを持つことが挙げられます。
> 
> Next.js 9.1からは、アプリケーションのルートにpagesディレクトリを作成するのではなく、src/pagesディレクトリを作成することができるようになりました。
> 
> srcディレクトリの使用はオプションで、あなたの会社がすでにこの規格を導入している場合に対応します。

では次に、appディレクトリを使用するとどうなるのかなのですが、
どうやらこちらは公式ページを見ると、ルーティング関連の機能のようです。

https://beta.nextjs.org/docs/getting-started#introducing-the-app-router

現在はベータ版として提供されていて、まだstableにはなっていないようですね。
本番での使用は避けておいた方がよさそう。

というわけで、もし2023年3月現在の時点で、本番環境でNextを動かしたい場合は、src/ディレクトリのみYesを選択しておくのがよさそうです。

https://reffect.co.jp/react/next-js-13-app

さて、前提が揃ったのでまずは静的なページの開発から行っていきましょう。

## 静的なページを追加していく

https://zenn.dev/toono_f/articles/1774dc83548079

https://typescriptbook.jp/tutorials/nextjs


まずはstaticなページを追加していきます。

現時点で、ローカルサーバーの3000ポートにアクセスした時に表示されるのは、 `src/pages/index.tsx` です。

少しコードをいじって、静的ページの追加とページ遷移を実現してみます。

```src/pages/index.tsx
import Head from 'next/head'
import { Inter } from 'next/font/google'
import styles from '@/styles/Home.module.css'
import Link from 'next/link'

const inter = Inter({ subsets: ['latin'] })

export default function Home() {
  return (
    <>
      <Head>
        <title>Create Next App</title>
        <meta name="description" content="Generated by create next app" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <main className={styles.main}>
        <section>
          {/* <h1>init</h1> */}
          {/* <p>the game has only just began</p> */}
          <h2>最新の記事一覧</h2>
          <p><Link href="/blogs/2023-0319">テスト投稿</Link></p>
        </section>
      </main>
    </>
  )
}
```

以下のCSSファイルは、一旦既存のコードを全削除した上でコピペしてください。

```src/styles/globals.css
html,
body {
  padding: 0;
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
  line-height: 1.6;
  font-size: 18px;
}

* {
  box-sizing: border-box;
}

a {
  color: #0070f3;
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

img {
  max-width: 100%;
  display: block;
}
```

新しくディレクトリ、ファイルを追加します。

```src/pages/blogs/2023-0319.tsx
import type { FC } from 'react';
import Link from 'next/link';

const FirstPost: FC = () => {
	return (
    <>
      <h1>Test Post</h1>
      <p>
			<Link href="/">ホームに戻る</Link>
      </p>
    </>
  )
  
};
export default FirstPost;
```

これで、ページはこんな感じになりました。

![スクリーンショット 2023-03-19 19.33.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684929/51f591dc-e3db-49ff-bfe5-de831cb1534d.png)

また、 http://localhost:3000/blogs/2023-0319 とドキュメントルートの間でページ遷移が可能になっている事が確認できます。

これで、一先ずNext.jsで作成した静的なサイトをVercelでホスティングする事ができました。
ページを追加すれば記事を増やす事もできますし、ページ遷移も可能です。

とはいえ、現状のままではしんどいポイントもたくさんありますね。

- 記事を追加したい時、いちいちtsxファイルを作成する必要がある
    - CMSとしての機能が存在しない
    - プログラム側からしか記事を追加する術が存在しない
- アプリケーションっぽい機能が全く存在しない、静的なファイルしかない
    - UI側から記事を追加したいよね
    - UI側から記事を追加できるなら認証とか欲しいよね
    - 認証があるなら自分のプロフィールも作りたいよね

というわけで、引き続きこのあたりの仕組みを実装していきます。

（WIP）：Next.jsで匿名認証を導入する
（WIP）：Next.jsでアプリケーションを作成する