React触ったことない人間が、Next.jsでアプリ作成し高速でVercelにデプロイするまで

#■はじめに
・目的はNext.jsの大枠に触れてみるというところです。
　※学習コストの低いVueを使ってポートフォリオを作成したもののNext.jsが気になりすぎて:wink:
　※そのため、アプリ作成と書いてはいますが、アプリの具体的な中身はほぼ空っぽです。
　※今後、簡単なプロフィールサイトを作成していく予定です
#■デプロイ先
 ・Vercel(https://profsite.vercel.app/)
#■手順
##１.環境構築
・next.jsのプロジェクト作成

```
npx create-next-app profsite
```

・ターミナルでプロジェクトディレクトリに移動

```
cd profsite
```

##２.node.jsのインストール(ver10.13 以上必要)
・バージョン確認

```
node -v
```

※未インストールの場合(こちらの記事がとてもわかりやすいです。)
　https://qiita.com/kyosuke5_20/items/c5f68fc9d89b84c0df09

##３.ローカルサーバー起動
・コンパイル

```
npm run dev
```

・http://localhost:3000へアクセスするとトップ画面が表示される

##４.Editorでトップ画面を少し編集してみる
・/pages/index.jsを編集すると、トップ画面が変更される(pages/index.js = ルート)
<img width="500px" alt="代替テキスト" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/735188/6e54ca5d-579e-b82c-53da-80e242dd1632.png">

##５.新しくディレクトリを切ってみる
・pages/skills/my-skills.jsを作成(自身のスキルセットを表示するページを想定)

```
export default function showSkills() {
　return (
　　<h1>My Skills</h1>
)}
```
・http://localhost:3000/skills/my-skillsへアクセスすると表示される
　つまり、作成したディレクトリ構造がそのままURLになる

【ブラウザ】
<img width="500px" alt="代替テキスト" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/735188/f4962f58-96d9-afcf-85d8-748e55344c4c.png">

##６.クライアントサイドナビゲーション
・ページ遷移をクライアント側のjavascript処理で実行し、サーバには通信を行わないのでサクサク:relaxed:
・リンクコンポーネントを使用する必要があるので、index.jsに読み込む　
【index.js】

```
import Link from 'next/link'

export default function Home() {
　return (
　　<Link href="/skills/my-skills"><a>My Skills</a></Link>
)}
```

※余談
>Adjacent JSX elements must be wrapped in an enclosing tag

・エラーがでてしまった
コンポーネントを以下のように、div等の要素で囲んで上げる必要がある
 (Reactで作成するコンポーネントは、 トップレベル（一番親となる階層）の要素を
 一つにする必要があるため)



【index.js】

```
import Link from 'next/link'

export default function Home() {
　return (
　　<div>
　　　<Link href="/skills/my-profile"><a>My Profile</a></Link>
　　　<Link href="/skills/my-works"><a>My Works</a></Link>
　　　<Link href="/skills/my-skills"><a>My Skills</a></Link>
　　　<Link href="/skills/contact"><a>Contact</a></Link>
　　</div>
)}
```

【ブラウザ】
お粗末ですが、ヘッダーメニュー
<img width="500px" alt="代替テキスト" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/735188/d86f4425-b946-3115-e00a-05361e1ef38c.png">

リンクをクリックするとクライアントサイドナビゲーション(ページ遷移をクライアント側のjavascript処理で実行し、サーバには通信を行わない)が動作するので、サクサクです。

【ブラウザ】
静止画だと伝わりにくいですが…
<img width="500px" alt="代替テキスト" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/735188/25647a3a-a3c6-b94d-093f-a5bdc309e5ac.png">


##７.画像ファイルの読み込み
・publicフォルダでurl(src)を管理している
・publicをルートとしたルートパスで記載する
<img width="500px" alt="代替テキスト" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/735188/08de6db9-8b2d-45af-018e-2b28003638d4.png">
【my-profile.js】

```
export default function showProfiles() {
　return (
　　<div>
　　　<h1>My Profile</h1>
　　　<div>
　　　　<img src="/myface.JPG" alt="私の画像" />
　　　</div>
　　</div>
)}
```

##８.メタデータ編集
・headコンポーネントを使用することで、headタグをページごとに設定できる
・下記は一例
【index.js】

```
import Link from 'next/link'
import Head from 'next/head'

export default function Home() {
　return (
　　<div>
　　　<Head>
　　　　<title>home</title>
　　　</Head>
　　　<Link href="/profile/my-profile"><a>My Profile</a></Link>
　　　<Link href="/works/my-works"><a>/My Works</a></Link>
　　　<Link href="/skills/my-skills"><a>/My Skills</a></Link>
　　　<Link href="/contact/contact"><a>/Contact</a></Link>
　　</div>
)}
```

【ブラウザ(titleは"home")】
<img width="500px" alt="代替テキスト" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/735188/b1fc404e-87c9-06dd-fe7a-a374db40880b.png">

【my-profile.js】

```
import Head from 'next/head'

　export default function showProfiles() {
　　return (
　　　<div>
　　　　<Head>
　　　　　<title>my profile</title>
　　　　</Head>
　　　　<h1>My Profile</h1>
　　　　<div>
　　　　　<img src="/myface.JPG" alt="私の画像" />
　　　　</div>
　　　</div>
)}
```

【ブラウザ(titleは"my profile")】
<img width="500px" alt="代替テキスト" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/735188/172f15ce-cfc8-954f-203a-f562ba304ae0.png">

##９.cssでレイアウトを変更してみる
・小さなcss modulesを作成後、layoutコンポーネントを対象のjsコンポーネントにラップすることで、
　cssを適用することが可能
・cssモジュールは基本、機能ごとに分ける。(文字のサイズ、フォントを整えるためのモジュール、画像のサイズを整えるためのモジュール等)
・ルートにcomponentsディレクトリを作成しlayout.jsを配置
　/components/layout.js

【layout.js】
※childrenはreactの特別なpropsの書き方(Layoutコンポーネントで囲まれた要素を返す)

```
export default function Layout({ children }) {
　return (
　　<div>{children }</div>
)}
```

・コンポーネント(どれでも良い。例としてmy-profile.js)をLayoutコンポーネントでラップする

【my-profile.js】

```
import Head from 'next/head'
import Layout from '../../components/layout'

export default function showProfiles() {
　return (
　　<div>
　　　<Layout>
　　　　<Head>
　　　　　<title>my profile</title>
　　　　</Head>
　　　　<h1>My Profile</h1>
　　　　<div>
　　　　　<img src="/myface.JPG" alt="私の画像" />
　　　　</div>
　　　</Layout>
　　</div>
)}
```

・上記だけだとdivで囲んだだけなので、css moduleを使ってレイアウトを変更する
・/componentsディレクトリにlayout.module.cssを作成(※拡張子は必ず.module.css)
【layout.module.css】

```
.container {
　max-width: 36rem;
　padding: 0 1rem;
　margin: 3rem auto 6rem;
}
```

・layout.module.cssを読み込んで、layout.jsのclassNameに適用する
【layout.js】

```
import styles from './layout.module.css'

export default function Layout({ children }) {
　return (
　　<div className={ styles.container }>
　　　{ children }
　　</div>
)}
```

【ブラウザ】
・Layoutコンポーネントにラップされている要素にcssが適用される
<img width="500px" alt="代替テキスト" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/735188/3372ccaf-0690-82ed-7b33-8724c2387d6d.png">
※class名がユニークな値になる仕様
<img width="300px" alt="代替テキスト" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/735188/cb931dd3-9d88-a0c0-5532-1b40bd504a52.png">

##１０.グローバルcssを適用する
・_app.js(pages/_app.js)にimportしたcssは全てのコンポーネントに適用される
・大元のglobals.cssは_app.jsでのみimportすることができる
・つまり、globals.cssの内容を_app.jsにimportすれば全コンポーネントにcssが適用されるということ

【_app.js】

```
import '../styles/globals.css'

function MyApp({ Component, pageProps }) {
　return <Component {...pageProps} />
}
export default MyApp
```

【styles/globals.css】
・わかりやすいように、テキストカラーを赤に。

```
html,
body {
　color:red;
　padding: 0;
　margin: 0;
　font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
　Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
}
a {
　color: inherit;
　text-decoration: none;
}
* {
　box-sizing: border-box;
}
```

【ブラウザ】
全てのページのテキストカラーが赤に。
<img width="500px" alt="代替テキスト" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/735188/ed43ec9d-2987-3a3f-c768-41529e9931e2.png">
<img width="500px" alt="代替テキスト" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/735188/7eb79365-37b1-9ff2-07ac-7f4c519d0b74.png">
<img width="500px" alt="代替テキスト" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/735188/39c9840a-dbc9-acf6-a9a6-0f0e676f8852.png">

##１１.gitにpush
いつものやつなので、割愛。。
・githubでリポジトリ作成
・gitにpush

```
cd profsite
git init
git remote add origin https://github.com/masayan1126/profsite.git
git remote -v 
git add .
git commit -m ""
git push -u origin master
```

##１２.Vercel(バーサル)へデプロイ
・初期設定でデプロイすると、static generation(コンパイル時にHTML生成)が適用される
・カスタムドメイン(取得した有料ドメインを使用することも可能)
・自動でSSL化されている(すご:joy:)
・アカウント作成
　ここからは画面の指示通りで簡単な手順なので詳細は割愛します。
　githubのアカウントサインインし、あとはプロジェクト名とか、取り込み対象の
 リポジトリを選択してデプロイして完了です。
【リポジトリのインポート】
<img width="500px" alt="代替テキスト" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/735188/2956c36c-1a99-b396-ef28-2aa81ff3d5a0.png">
【デプロイ完了】
<img width="500px" alt="代替テキスト" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/735188/0cfecb4f-a000-bcfb-5e9b-0a44f3e66d45.png">

#■最後に
・Next.jsを作られた方、天才すぎます!!:sob:
・所要時間は2時間くらいで、この記事を書く時間よりも短かったです。(笑)