Next.js × TypeScript × Firebaseでポートフォリオ

## はじめに
初投稿です。
Next.js / TypeScript / Firebaseを使ってポートフォリオサイトを作ってみました。
作ったあとでNextのルーティング機能とかいらなかったなと思ったのは秘密...

デプロイしたのでとりあえず公開。
作り方を初学者の方向けにまとめてみました！ご意見いただけると嬉しいです！

随時更新します！

## お前誰？
[こういう者です...（成果物）](https://portfolio-6b4b9.firebaseapp.com/)
最近は自作キーボードを作ったり、スタートアップ企業で2社ほどお手伝いさせていただいています！(ただの手伝いですが……)

## 誰向けの記事？
React, Next.jsのチュートリアルくらいはやったことある！という初学者の方向けです。

## 目次
1. Hello World
2. _app.tsx / _document.tsx
3. Material-UI
4. 画像
5. デプロイ

参考資料

## 1. Hello World
### Next.jsをインストール
```sh:~/workspace/portfolio
$npm init -y
$npm install --save react react-dom next
$npm install --save-dev typescript @types/react @types/node
$mkdir pages
$touch pages/index.tsx
```
補足：[@types/~は型定義ファイル](https://qiita.com/Nossa/items/726cc3e67527e896ed1e)

### git始めます
※gitでコード管理していない人はとばしてください！

```sh:~/workspace/portfolio
$git init
# 忘れずに.gitignoreを書き変えましょう
$vi .gitignore
```
```sh:.gitignore
.DS_store

# next.js build output
.next
.next/

# Logs
npm-debug.log*

.vscode/

# node.js
node_modules/
npm-debug.log

# dotenv environment variables file (build for Zeit Now)
.env
.env.build
```
追記し終わったら...

```sh:~/workspace/portfolio
$git add .
$git commit
$git remote add origin https://github.com/hoge/fuga.git
$git push origin master
```
### では、HelloWorldしましょう。
```jsx:pages/index.tsx
import { NextPage } from 'next';

const Home: NextPage = () => (
<h1>Hello world!</h1>
);

export default Home;
```
デバッグサーバを立てます。

```sh:~/workspace/portfolio
$npm run dev
```

localhost:3000にアクセスしてみましょう。
出来たてホヤホヤのHelloWorldがいるはずです！

## 2. _app.tsx / _document.tsx 
Next.jsで開発するなら、この2つのファイルをpages/ディレクトリに置いてください。
[まずはこちらの記事を参考に書いてみましょう！](https://blog.anozon.me/ts-nextjs-pages)


これらのファイルの詳しい説明は下記のブログが分かりやすかったので引用させていただきました。

>_document.tsxを書くと吐き出されるHTMLファイルの構成を変えることができ、_app.tsxを書くとすべてのRouteコンポーネントがここで書いた<App>コンポーネントによってラップされるようになります。
>　　　　　　　　　　　　　　　　　　　　　　　[TypeScriptでNext.js 9を触った感想ーkohei.dev](https://www.kohei.dev/posts/7-tips-of-next-js-9-with-typescript?hl=ja-JP)
>



## 3. [Material-UI](https://material-ui.com/)
Google Material Design のガイドラインに沿ったデザインフレームワーク。
多機能かつ洗練されていて素晴らしいと思います。
たまに痒いところに手が届かないですが...

早速インストール！

```sh:~/workspace/portfolio
$npm install @material-ui/core @material-ui/icons @material-ui/styles @material-ui/lab
```

Hello Worldしていきましょう！

```jsx:pages/index.tsx
import { NextPage } from 'next';
import { Button } from '@material-ui/core';

const Home: NextPage = () => (
    <Button variant="contained" color="primary">
      Hello World
    </Button>
);

export default Home;
```

Hello Worldボタンができました。

### tsconfig.json
さて、[こちらのページ](https://material-ui.com/guides/typescript/)を見ながらMaterial-UI用のtsconfig書いていきましょう

```json:tsconfig.json
{
  "compilerOptions": {
    "target": "es6",
    "lib": [
+     "es6"
+     "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
+   "noImplicitAny": true,
+   "noImplicitThis": true,
+   "strictNullChecks": true
  },
  "exclude": [
    "node_modules"
  ],
  "include": [
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx"
  ]
}
```

### font-awesome
Material-UIのアイコンだけで物足りない！という人はfont-awesomeを使ってみてください。
もちろんMaterial-UIのIconコンポーネントが対応しています。
    
[font-awesome](https://fontawesome.com/icons/react?style=brands)

### ~~スッスッ~~ 
<span style="color: #d61b09">※上下スクロールのシングルページにしたのでやめました</span>
~~`react-swipeable-views`でページがスッスッと動くUIを作れます。~~
~~詳しくはMaterial-UIのTagsコンポーネントをみてね~~

```sh:~/workspace/portfolio
$npm i --save react-swipeable-views @types/react-swipeable-views
```
    
## 4. 画像
##### 前提
next.jsではpublicという名前のディレクトリに静的ファイルを置く必要があります。
[公式リンク](https://nextjs.org/docs/basic-features/static-file-serving)

publicを作成して、その配下に画像をおきましょう。

```sh:~/workspace/portfolio
$mkdir public
$mv ~/hoge.png public/
```

##### プラグイン
[next-images](https://github.com/zeit/next-plugins)というプラグインがあります
画像の表示にはこちらを使ってみました。

```sh:~/workspace/portfolio
$npm install --save next-images @types/next-images
```
↓インストールできたら、以下で画像表示ができるはず！

```js:next.config.js
const withImages = require('next-images');
module.exports = withImages();
```


## デプロイ
タイトル通り、デプロイはFirebaseで行います。
今回はFirebase Hostingに静的ページとしてデプロイしましょう。

まずは、firebase-toolsを導入。

```sh:~/workspace/portfolio
# firebaseと接続するツール
$npm i -g firebase-tools

# projectIDを記述
$vi .firebaserc
```

続いて[Firebase Console](
https://console.firebase.google.com/u/0)にアクセスし、プロジェクトを作成。
プロジェクトのIDを取得してください！
取得できたら書き加える...

```json:.firebaserc
{
  "projects": {
    "default": "xxxxxxxxx"
  }
}
```

```sh:~/workspace/portfolio
$firebase login
# このコマンドでプロジェクトが表示されたら成功！
$firebase projects:list 
```

package.jsonのscriptsにexportコマンドを追加。

```json:package.json
{
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "next",
    "deploy": "firebase deploy",
    "build": "next build",
    "start": "next start",
    // exportを追加
    "export": "next export"
  },
}
```

Firebase Hostingの設定を書きます。

```json:firebase.json
{
  "hosting": {
    "public": "out",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ]
  }
}
```
```:補足
next.jsの静的ファイル置き場のディレクトリ名はpublicでした。
Firebase Hostingでデフォルトの公開ファイル置き場もpublicなので書き換えます。

https://nextjs.org/learn/excel/static-html-export
```

ビルドしたファイルをまとめて静的ページにしてデプロイするためのフォルダを作りましょう。

```sh:~/workspace/portfolio
$mkdir out
```

できたら準備完了。いよいよデプロイ。

```sh:~/workspace/portfolio
$npm run build && npm run export

$firebase deploy
```

表示されたHosting URLにアクセスしてみましょう！


## 参考資料
##### UI
[Reactでポートフォリオを作ってみた](https://qiita.com/Kentaro91011/items/e768429139f13680efde)
[爆速デザイン](https://qiita.com/kyrieleison/items/39ce30dd2d204791a9ea)

##### 環境
[環境構築](https://qiita.com/otsukayuhi/items/c7a907702d58bfc729b1)
[コミッターのquiita](https://qiita.com/nkzawa/items/1e0e93efd13fb982c8c0)

##### 実装 / アーキテクチャ
[Next.js on Cloud Functions for Firebase with Firebase Hosting](https://codeburst.io/next-js-on-cloud-functions-for-firebase-with-firebase-hosting-7911465298f2)
[Next.jsとFirebaseで更新の手間がかからないポートフォリオサイトを作ってみた](https://qiita.com/kentaro_m/items/51ba502fd5b1c603a439)
[Typescript + React、Firebase Hosting & Functions、Github GraphQL APIを使って自分のポートフォリオサイトを作った。](https://medium.com/@teitei_tk/create-portfolio-site-on-firebase-715677dd74eb)
[firebase上でtypescriptで書かれたnextjsを動かす](https://dream-yt.github.io/post/firebase-next-typescript/)
[ちょっと真面目なNext.js【Firebase Hosting編】](https://qiita.com/ovama-koffee/items/55e6aee106d1399b5c09)