Nuxt.js チートシート

# はじめに
Nuxtに関してのチートシートです。
いちいち調べるのもめんどくさくなってきたので基本的な部分をまとめてみました。
自分用のチートシートにはなりますが、開発中の初心者の方も参考にしてください。
今後はLaravelでバックエンド、Nuxt.jsでフロントエンドを構築したいのでその辺も記載していきます。

## Nuxt.jsのインストールから初期設定
### Nuxt.jsのインストール
```terminal:ターミナル
npx create-nuxt-app (フォルダ名)
```

#### プロジェクト名の入力
このままでOK

```terminal:ターミナル
✨  Generating Nuxt.js project in nuxt-first
? Project name (フォルダ名)
```

#### 言語の選択
```terminal:ターミナル
? Programming language: (Use arrow keys)
❯ JavaScript 
  TypeScript 
```

#### パッケージマネージャーの選択
```terminal:ターミナル
? Choose the package manager (Use arrow keys)
❯ Yarn 
  Npm 
```

#### UIフレームワークの選択
```terminal:ターミナル
? Choose UI framework (Use arrow keys)
❯ None 
  Ant Design Vue 
  BalmUI 
  Bootstrap Vue 
  Buefy 
  Chakra UI 
  Element 
  Framevuerk 
  iView 
  Tachyons 
  Tailwind CSS 
  Vuesax 
  Vuetify.js 
  Oruga 
```

#### モジュールの選択
**Axios**
【必須】ブラウザやnode.jsで動くPromiseベースのHTTPクライアントであり、REST-APIを実行したいときなどに使うと実装が簡単にできます。

**PWA**
【任意】モバイルサイト上でアプリのようなユーザー体験を提供する技術です。
ホーム画面へのアイコン追加やプッシュ通知も可能で、ユーザーとの接触機会を増やすことができます。
それだけでなく、読み込み速度や表示の高速化、オフラインでの閲覧可など、さまざまなメリットが得られます。

**Content**
【任意】`content/`ディレクトリにMarkdownで記載すると記事ができる。
Markdownで記入しなければいけないのでどちらかというとエンジニア向けな気がする。
[MicroCMS](https://microcms.io/)の方がノンエンジニアでも使いやすい。


```terminal:ターミナル
? Nuxt.js modules: (Press <space> to select, <a> to toggle all, <i> to invert se
lection)
❯◯ Axios - Promise based HTTP client
 ◯ Progressive Web App (PWA)
 ◯ Content - Git-based headless CMS
```

#### Lintツールの選択
```terminal:ターミナル
? Choose linting tools (Press <space> to select, <a> to toggle all, <i> to inver
t selection)
❯◯ ESLint
 ◯ Prettier
 ◯ Lint staged files
 ◯ StyleLint
 ◯ Commitlint
```

https://qiita.com/soarflat/items/06377f3b96964964a65d

#### テストフレームワークの選択
```terminal:ターミナル
? Choose test framework (Use arrow keys)
❯ None 
  Jest 
  AVA 
  WebdriverIO 
  Nightwatch 
```

https://jestjs.io/ja/

https://qiita.com/rhistoba/items/6e90e2c51e8ad1875ac0

#### レンダリング方法の選択
**SSR**
Server Side Renderingの略で、サーバー側でレンダリングを行います。

**SPA**
Single Page Appの略で、ブラウザ側でレンダリングを行います。

```terminal:ターミナル
? Choose rendering mode (Use arrow keys)
❯ Universal (SSR) 
  Single Page App
```

##### SSRとSPAの違い

https://mintaku-blog.net/spa-ssr/

#### developmentターゲットの選択
**Server**
サーバーホスティングのためには target を server にします。

**Static**
静的ホスティング（サーバーが必要ないホスティング）の場合こちらを使います。

```terminal:ターミナル
? Deployment target: (Use arrow keys)
❯ Server (Node.js hosting) 
  Static (Static/JAMStack hosting) 
```

https://ja.nuxtjs.org/docs/2.x/get-started/commands/

#### developmentツールの選択
特に必要性はなさそう・・
理解してません。

```terminal:ターミナル
? Development tools: (Press <space> to select, <a> to toggle all, <i> to invert 
selection)
❯◯ jsconfig.json (Recommended for VS Code if you're not using typescript)
 ◯ Semantic Pull Requests
 ◯ Dependabot (For auto-updating dependencies, GitHub only)
```

#### GitHubのユーザ名の入力
```terminal:ターミナル
? What is your GitHub username? 
```

## ディレクトリ構成
### .nuxt
コンパイルを実行すると作成されます。

### assets
コンパイルが行われていないSass、Lent、Fontなどを保存します。

### components
再利用可能なコンポーネントファイルを保存します。

### layouts
各ページで共通となるヘッダーやフッターなどアプリケーション全体のレイアウトに関するコードを保存します。

### middleware
layoutやページがレンダリングする前に実行されるカスタム関数を保存します。

### node_modules
Nuxt.jsで使われるパッケージが保存されます。

### pages
ファイル名がURLとなるアプリケーションファイルです。

### plugins
Vueインスタンスが起動する前にロードするプラグインを保存します。

### static
robots.txtやfavicon、画像ファイルが保存されています。

### store
Vuexに関するファイルを保存します。

## 初期設定
### よく使うプラグイン紹介
#### Scss
```terminal:ターミナル
npm install sass-loader node-sass --save-dev
```

```vue:index.vue
<style lang="scss" scoped>
header {
  nav {
    background: eee;
  }
}
</style>
```

#### リセットCSS
様々な選択肢がありますが、私はcss-wipeを採用しています。

```terminal:ターミナル
npm install css-wipe --save
```

```vue:layouts/default.vue
<style lang="scss">
    // これでOK
    @import 'css-wipe';
</style>
```

#### FontAwesome
```terminal:ターミナル
// 必須（Solid Style）
npm install @fortawesome/vue-fontawesome @fortawesome/fontawesome-svg-core @fortawesome/free-solid-svg-icons --save

// 任意（Regular Style, Brands Style）
npm install @fortawesome/free-regular-svg-icons  --save
npm install @fortawesome/free-brands-svg-icons  --save
```

```js:plugins/fontawesome.js
import Vue from 'vue';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import { config, library } from '@fortawesome/fontawesome-svg-core';
// solid Style
import { faChevronLeft, faChevronRight, faTimes } from '@fortawesome/free-solid-svg-icons';
// regular Style
import { faCircle } from '@fortawesome/free-regular-svg-icons';
// brands Style
import { faChrome } from '@fortawesome/free-brands-svg-icons';

// nuxt.config.jsでCSSファイルを追加
config.autoAddCss = false;

// 利用するアイコンを配列に追加
const solidIcons = [faChevronLeft, faChevronRight, faTimes];
const regularIcons = [faCircle];
const brandsIcons = [faChrome];

// 利用するアイコンをlibraryに追加
solidIcons.forEach(icon => library.add(icon));
regularIcons.forEach(icon => library.add(icon));
brandsIcons.forEach(icon => library.add(icon));

// グローバルコンポーネントに登録
Vue.component('fa', FontAwesomeIcon);
```

```js:nuxt.config.js
export default {
    target: 'server',
    // cssに追記
    css: ['@fortawesome/fontawesome-svg-core/styles.css'],
    plugins: [
　　　　　// pluginsに追記
        '@/plugins/fontawesome',
    ],
};
```

```vue:pages/index.vue
// Solid Style
<fa icon="chevron-left" area-hidden="true" />
// Regular Style
<fa :icon="['far', 'circle']" area-hidden="true" />
// Brands Style
<fa :icon="['fab', 'chrome']" area-hidden="true" />
```

`area-hidden="true"`**とは何か？**
「WAI-AREA」で定められている仕様の1つであり、trueが指定してある場合、ブラウザにその要素が非表示であるという事を明示的に伝えるものです。
アクセシビリティの向上のためにも必ずつけるべきです。

#### .env
Nuxt.jsのv2.13からはdotenvがビルトインでサポートされていますが、@nuxtjs/dotenvを使用します。

```terminal:ターミナル
npm install @nuxtjs/dotenv --save
```

```js:nuxt.config.js
// dotenvを読み込む
require("dotenv").config();
// .envに記載している値を記載
const { API_KEY, DEMO_KEY } = process.env;

export default {
    modules: [
        '@nuxtjs/dotenv',
    ],
    env: {
        API_KEY,
        DEMO_KEY
    }
}
```

#### axios
Nuxt.jsでは、通常のaxiosとnuxt.js用のモジュールの@nuxtjs/axiosを利用することができます。
今回は、@nuxtjs/axiosを使います。

```javascript:index.vue
async asyncData({ $axios }) {
        const prefectures = await $axios.$get('https://meeting.microcms.io/api/v1/prefectures', {
            headers: {
                'X-API-KEY': process.env.API_KEY,
            },
        });

        return {
            prefectures,
        };
    },
```

##### コンポーネントで使うとき
asyncDataメソッドはページコンポーネント（pages/）でしか使えず、通常のコンポーネント(components/)では使用できません。

これを回避するためには2通りの方法があります。
**①`mounted`を使う**
**②`v-bind`, `props`を使う**

①の問題点はSSRでは使えません。
②の問題点は可読性が落ちます。
どちらかというと②の方がマシなので②を使います。

```vue:pages/index.vue
template>
    <div class="container">
        <!-- v-bindでprefecturesを渡す（親コンポーネント） -->
        <AreaSort :prefectures="prefectures" />
    </div>
</template>

<script>
import AreaSort from '@/components/Element/AreaSort';

export default {
    async asyncData({ $axios }) {
        const prefectures = await $axios.$get('https://meeting.microcms.io/api/v1/prefectures', {
            headers: {
                'X-API-KEY': process.env.API_KEY,
            },
        });

        return {
            prefectures,
        };
    },
    components: {
        AreaSort,
    },
    data() {
        return {
            prefectures: '',
        };
    },
};
</script>
```

```vue:components/Element/AreaSort.vue
<template>
    <div class="area-container" id="area">
        <h2 class="heading">エリアをお選びください</h2>
        <div class="area-wrapper">
            <nuxt-link
                class="area-button"
                v-for="content in prefectures.contents"
                :key="content.id"
            >
                {{ content.prefectures }}
            </nuxt-link>
        </div>
    </div>
</template>

<script>
export default {
    // propsで値を受け取る（子コンポーネント）
    props: ['prefectures'],
};
</script>
```