【Nuxt.js】サイト構築前にやること

静的サイトを作成する際、`create-nuxt-app`（プロジェクト作成）後に行う環境設定を備忘録としてまとめています。
都度、更新・変更するかもです。

# 目次

1. [ESLintを追加する](https://qiita.com/mt877/items/722b17808c8677c5d0fd#eslint%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B)
2. [SASS（SCSS）の使用](https://qiita.com/mt877/items/722b17808c8677c5d0fd#sassscss%E3%81%AE%E4%BD%BF%E7%94%A8)
3. [共通JSの読み込み](https://qiita.com/mt877/items/722b17808c8677c5d0fd#%E5%85%B1%E9%80%9Ajs%E3%81%AE%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%81%BF)
4. [html/head/bodyタグの編集（サイト共通）](https://qiita.com/mt877/items/722b17808c8677c5d0fd#htmlheadbody%E3%82%BF%E3%82%B0%E3%81%AE%E7%B7%A8%E9%9B%86%E3%82%B5%E3%82%A4%E3%83%88%E5%85%B1%E9%80%9A)
5. [ローカルサーバーのホスト・ポート番号を変更](https://qiita.com/mt877/items/722b17808c8677c5d0fd#%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%81%AE%E3%83%9B%E3%82%B9%E3%83%88%E3%83%9D%E3%83%BC%E3%83%88%E7%95%AA%E5%8F%B7%E3%82%92%E5%A4%89%E6%9B%B4)
6. [build設定](https://qiita.com/mt877/items/722b17808c8677c5d0fd#build%E8%A8%AD%E5%AE%9A)
7. [画像の保存先について](https://qiita.com/mt877/items/722b17808c8677c5d0fd#%E7%94%BB%E5%83%8F%E3%81%AE%E4%BF%9D%E5%AD%98%E5%85%88%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)




# ESLintを追加する

全てのJavaScriptとVueファイルをlintします。除外したいファイルは`.gitignore`に定義します。
Nuxt.jsではESLintの設定は`.eslintrc.json`ではなく、`.eslintrc.js`で設定します。

## 各種パッケージをインストール。

```
npm install -D babel-eslint eslint eslint-loader eslint-plugin-vue
```

## `.eslintrc.js`を作成しオプション等を設定・記述する。

```.eslintrc.js
module.exports = {
  root: true,
  env: {
    browser: true,
    es6: true,
    node: true
  },
  parserOptions: {
    parser: 'babel-eslint'
  },
  extends: [
    'eslint:recommended',
    'plugin:vue/recommended'
  ],
  globals: {
    "$": false,
    "jQuery": false
  },
  // *.vueファイルをlintにかけるために必要
  plugins: [
    'vue'
  ],
  rules: {
    'indent': ['error', 2],
    'linebreak-style': ['error', 'unix'],
    'quotes': ['error', 'single'],
    'semi': ['error', 'always'],
    'no-console': ['warn'],
    'no-unused-vars': ['warn'],
    'vue/max-attributes-per-line': 'off',
    'vue/singleline-html-element-content-newline': 'off'
  }
};
```

## `package.json`に`lint`タスクを追加します。

```package.json
"scripts": {
  "lint": "eslint --ext .js,.vue --ignore-path .gitignore ."
}
```

## 開発中、保存時に自動でESLintを実行するには`nuxt.config.js`に以下を追記してください。

```nuxt.config.js
build: {
  extend(config, ctx) {
    // 保存時にESLintを実行
    if (ctx.isDev && ctx.isClient) {
      config.module.rules.push({
        enforce: "pre",
        test: /\.(js|vue)$/,
        loader: "eslint-loader",
        exclude: /(node_modules)/
      })
    }
  }
}
```

参考URL：[開発ツール - NuxtJS](https://ja.nuxtjs.org/guide/development-tools#eslint-%E3%81%A8-prettier)




# Sass（SCSS）の使用

## 必要なパッケージをインストール。

### LibSass（node-sass）を使う場合

```
% npm install -D node-sass sass-loader
```

### Dart Sass（sass）を使う場合

```
% npm install -D sass sass-loader fibers
```

インストール・設定後、styleタグにlang属性を追加すれば認識してくれます。

```vue:hoge.vue
<style lang="scss">
  .hoge {
    &__child {
    }
  }
</style>
```

## `.browserslistrc`をルートディレクトリに追加

[browserslist](https://github.com/browserslist/browserslist)を参考にコンパイルの対象ブラウザを記述してください。

```.browserslistrc
last 2 version
Firefox ESR
Chrome 28
not dead
```

## 共通SCSSを読み込み

サイト共通で読み込みたいCSSがある場合は`nuxt.config.js`にパスを記述します。

```nuxt.config.js
export default {
  css: [
    { src: '@/assets/scss/style.scss', lang: 'scss' },
  ]
}
```

## SCSSをグローバル化

SCSSの変数やmixinを各コンポーネントで使用したい場合は「@nuxtjs/style-resources」をインストール。

#### @nuxtjs/style-resources

URL：[@nuxtjs/style-resources](https://www.npmjs.com/package/@nuxtjs/style-resources)

```
% npm install -D @nuxtjs/style-resources
```

`nuxt.config.js`にモジュールと該当ファイルのパスを記述します。

```nuxt.config.js
export default {
  modules: [
    '@nuxtjs/style-resources',
  ],
  styleResources: {
    scss: [
      '@/assets/scss/_var.scss',
      '@/assets/scss/_mixin.scss',
    ]
  }
}
```




# 共通JSの読み込み

1. 外部リソースの読み込み
2. `static`から読み込み
3. `plugins`から読み込み
4. `middleware`から読み込み
5. 外部リソースの読み込みについて補足

## 外部リソースの読み込み

外部プラグイン・CDN読み込みたい場合はこれ

- `async`：非同期
- `defer`：遅延
- `body`：`</body>`の直前に追加

```nuxt.config.js
export default {
  head: {
    script: [
      { src: 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js', async: true, defer: true, body: true },
      { src: 'https://polyfill.io/v3/polyfill.min.js?version=3.52.1' },
    ]
  }
}
```

参考URL：[外部リソースを使うには？ - NuxtJS](https://ja.nuxtjs.org/faq/)

## `static`から読み込み

webpackで処理されることを意図しないファイルを読み込む場合はこれ。
外部リソースと同じ方法で読み込みます
`static`フォルダに該当ファイルを追加して`nuxt.config.js`にパスを記述します。

```nuxt.config.js
export default {
  head: {
    script: [
      { src: 'js/common.js', body: true }
    ]
  }
}
```

## `plugins`から読み込み

Vueアプリケーションがが初期化される前にインポートしたい場合はこれ。
webpackで処理したい自作のJSを読み込ませる場合、この方法を利用しています。
`plugin`フォルダに該当ファイルを追加して`nuxt.config.js`にパスを記述します。

- `mode`：`client`クライアントサイドで実行。`server`サーバーサイドで実行

```nuxt.config.js
export default {
  plugins: [
    { src: '@/plugins/common.js', mode: 'client' }
  ]
}
```

参考URL：[API: plugins プロパティ - NuxtJS](https://ja.nuxtjs.org/api/configuration-plugins/)

## `middleware`から読み込み

Vueアプリケーションでルーティングが行われるタイミングで何かしたい場合はこれ。
今のところ具体的な用途がわからない。


## 外部リソースの読み込みについて補足

個人的な手法ですが、リソースのリクエストを減らす目的で、開発時に外部プラグインと自作JSを統合しています。
`plugins`フォルダに`import`フォルダを追加し、フォルダ内に外部プラグインのソースコードなどを入れておきます。
あとは自作JSの最初に該当ファイルをimportしておけば、トランスパイルで統合されたファイルが書き出されます。

```hoge.js
import './import/jquery.js';
import './import/slick.min..js';
```

外部プラグインにはESLintを動作させたくないので、動作範囲から`import`フォルダを除外します。
`.eslintignore`を作成し、除外記述を追加します。

```.eslintignore
plugins/import/*
```




# html/head/bodyタグの編集（サイト共通）

個人的に追加した要素だけ記述しています。

- `titleTemplate`：タイトルタグのテンプレート
- `htmlAttrs`：htmlタグの属性指定
- `bodyAttrs`：bodyタグの属性指定

```nuxt.config.js
export default {
  head: {
    titleTemplate: '%s | SAMPLE SITE',
    htmlAttrs: {
      lang: 'ja',
      class: ['html-class']
    },
    bodyAttrs: {
      class: ['body-class']
    }
  }
}
```




# ローカルサーバーのホスト・ポート番号を変更

ローカルIPアドレスでアクセスできるようにして、仮想環境や別デバイスで確認できるように設定します。

```nuxt.config.js
export default {
  server: {
    port: 3000,
    host: '0.0.0.0'
  }
}
```

参考URL：[https://ja.nuxtjs.org/faq/host-port/](https://ja.nuxtjs.org/faq/host-port/)




# build設定

## postcss

SCSSコンパイルの設定です。
- `autoprefixer`：autoprefixerでgridをIEに対応させています。

```nuxt.config.js
export default {
  build: {
    postcss: {
      preset: {
        autoprefixer: { grid: true }
      }
    }
  }
}
```

参考URL：[API: build プロパティ - NuxtJS](https://ja.nuxtjs.org/api/configuration-build/#postcss)

## babel

babelの設定です。

- `targets`：ビルドのターゲットを指定します。
  - `server`ビルドと`client`ビルドでターゲットの初期値が異なります。`server`ビルドでは`node: 'current'`、`client`ビルドでは`ie: '9'`になります。
  - `envTarget`では各ビルドのターゲットを定義しています。`client`側に空のオブジェクトを定義しておけば`.browserslistrc`の設定を参照してくれます。
- `useBuiltIns`：polyfillの処理方法を設定します
  - `usage`または`entry`を指定すると`core-js`（polyfillライブラリ）でpolyfillが補完されます。
  - `usage`は必要なpolyfillだけを自動で判別してインポートしてくれます。
  - `entry`は個別に手動でpolyfillをインポートします。
- `corejs`：core-jsの読み込みバージョンを指定します。

```nuxt.config.js
export default {
  build: {
    babel: {
      presets({ envName }) {
        const envTarget = {
          server: { node: "current" },
          client: {},
        };
        return [
          [
            require.resolve('@nuxt/babel-preset-app'),
            {
              targets: envTarget[envName],
              useBuiltIns: "usage",
              corejs: { version: 2 }
            }
          ]
        ]
      }
    }
  }
}
```

~~参考URL - 1：[Babel7.x時代のpolyfillの設定方法とuseBuiltInsの仕組み](https://aloerina01.github.io/blog/2018-11-29-1)~~
参考URL - 2：[Babel7.4で非推奨になったbabel/polyfillの代替手段と設定方法](https://aloerina01.github.io/blog/2019-06-21-1)




# 画像の保存先について

環境構築から脱線しますが、画像リソースの保存先として`assets`フォルダと`static`フォルダの使い分けを補足しておきます。
基本的に、webpackで処理したいファイルは`assets`、それ以外は`static`で使い分けています。

## `assets`フォルダ
こちらに格納したファイルはデータURL（Base64）に変換、インライン化されます。
webpackで処理したいファイルはこちらに格納します。

### `assets`フォルダの画像参照方法
最初にエイリアスを記述するのがポイントです。

```hoge.vue
<img src="~/assets/images/image.png">
<img src="@/assets/images/image.png">
```

```hoge.scss
background: url("~assets/images/image.png");
background: url("~@/assets/images/image.png");
```

## `static`フォルダ
webpackで処理したくないファイルはこちらに格納します。

### `static`フォルダの画像参照方法

```hoge.vue
<img src="/images/image.png">
```

```hoge.scss
background: url("/images/image.png");
```

参考URL - 1：[アセット - NuxtJS](https://ja.nuxtjs.org/guide/assets/)
参考URL - 2：[【Nuxt.js】imgファイルの指定方法について](https://qiita.com/hiroyukiwk/items/a26e767d193ef8d9155b)