nuxt.js導入とかPWA化のメモ

# 前置き

vue初心者こと私がnuxtでのPWAの設定をとりあえず頑張ったときのメモとかエラーとか。

# 準備

vue-cliのインストールをしていなかったらいれる。

```bash
npm install -g vue-cli
```

# インストールと起動（スターターテンプレートで始める）

スターターテンプレートがあるようなのでそれをいれてみる。

[nuxt-community/starter-template](https://github.com/nuxt-community/starter-template)


```bash
vue init nuxt-community/starter-template プロジェクト名
cd プロジェクト名
npm install
```

起動してみる

```bash
npm run dev
```

 http://localhost:3000で確認



# インストールと起動（ノースターターテンプレート）
スターターテンプレートを使わずにいれる。
作業フォルダ内にpackage.jsonを作成、または既存のものを修正したり、一から作る場合とか。

```javascript:package.json
{
  "name": "my-app",
  "scripts": {
    "dev": "nuxt"
  }
}
```


```bash
npm install --save-dev nuxt
```

スターターテンプレートはディレクトリ構造通りにフォルダがあるけど、
nuxt単品でインストールした場合は自分でディレクトリを作っていれる

#### [nuxt公式ディレクトリ構造](https://ja.nuxtjs.org/guide/directory-structure)

- assets
 - コンパイルが必要なjsやcssをいれる
- static
 - コンパイルしなくてもいい静的ファイル
- components
 - パーツとしてのvueファイル（ヘッダーのみとか、検索バーのみとか）
- pages
  - ルーティングしたページ単位のvueファイル。レイアウトより内側
- layouts
  - 大枠のvueファイル
- middleware
  - ルーティングしたそれぞれのルートで使う共通のロジック
- plugins
 - クライアントサイド限定で使用するプラグイン
 - [nuxt公式：クライアントサイド限定のプラグイン利用](https://ja.nuxtjs.org/guide/plugins#%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88%E3%82%B5%E3%82%A4%E3%83%89%E9%99%90%E5%AE%9A%E3%81%AE%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E5%88%A9%E7%94%A8)
- store
  -  Vuex ストア のファイルをいれる
  - [nuxt公式：Vuex ストア](https://ja.nuxtjs.org/guide/vuex-store)

 

### pages ディレクトリ作成

```bash
mkdir pages
```

### index.vueを作って下記をいれる

```vue:index.vue
<template>
  <h1>Hello world!</h1>
</template>
```

```bash
npm run dev
```

 `http://localhost:3000`で確認可能


# エラーが出たらnodeのバージョンを疑ってみる

nodeのバージョンがひくいと動かない。
nuxtjsの公式でのnodeの推奨バージョンを見つけきれなくて、古めのnodeでやったので
私の環境では`$npm run dev`時に下記のエラーで止まった。

```bash
const policies = this.options.render.csp.policies ? {...this.options.render.csp.policies} : null
```

他のプロジェクトですでに古いバージョンのnodeが入ってたら、
下記などを参考にnodebrewで元々使っていたバージョンのnodeととりあえずstable（最新版）をいれて、プロジェクトに応じて切り替えるようにした

[nodebrewでnode.jsのバージョン切り替え](https://qiita.com/teratsyk/items/51d64010cb341b54491b)


# 設定

設定はインストールディレクトリ直下にある`nuxt.config.js`をいじる
基本的に変更しなくても動くので必要に応じて書き換える。

[nuxt公式：設定](https://ja.nuxtjs.org/guide/configuration)


# PWA化

@nuxtjs/pwaをインストールして設定する

```bash
npm install --save-dev @nuxtjs/pwa
```

```js:nuxt.config.js
  modules: [
    '@nuxtjs/pwa'
  ],
  manifest: {
    name: 'nuxt-start',
    lang: 'ja',
    short_name: 'nuxt',
    title: 'nuxt-startです',
    'og:title': 'nuxt-startです',
    description: 'nuxt-startです',
    'og:description': 'nuxt-startです',
    theme_color: '#ffffff',
    background_color: '#ffffff'
  },
  workbox: {
    dev: true, //開発環境でもPWA
  },
```


git管理してる場合は、吐き出されたServiceWorker（sw.jsとかって吐き出される）を無視したいので.gitignoreに追加

``` git:.gitignore
sw.*
```

ビルドしてからサーバー起動してみる

```bash
npm run  build
npm run start 
```

http://localhost:3000

デベロッパーツールでService Workerが動いているか確認


# scssをつかえるようにする

```bash
npm install node-sass sass-loader --save-dev
```

.vueでstyleタグにlang="scss"をつけるとscssが使えるようになる



# globalにscssを使えるようにする

[nuxt公式：外部リソースを使うには？](https://ja.nuxtjs.org/faq/)
[nuxt公式：プリプロセッサを使うには？](https://ja.nuxtjs.org/faq/pre-processors)
[nuxt公式：css プロパティ](https://ja.nuxtjs.org/api/configuration-css/)

nuxt.config.jsに設定追加

プロジェクト内でsass/scssを使ってプリセッサ使う場合

```javascript:nuxt.config.js
  css: [
    { src: '~assets/sass/main.scss', lang: 'scss' }
  ],
```


assets/sass/にとりあえずsassっぽい記述でmain.scssを作る

```scss:main.scss

@charset "utf-8";

@mixin fs($size: 24, $base: 16, $important: false) {
  @if $important == 'important' or $important == true {
    $important: ' !important';
    font-size: $size + px'#{$important}';
    font-size: ($size / $base) * 1rem'#{$important}';
  } @else {
    $important: '';
    font-size: $size + px;
    font-size: ($size / $base) * 1rem;
  }
}

.fs42 {
  @include fs(42);
}

```

レイアウトから呼び出すのでlayoutsのdefault.vueに下記を追加

```vue:default.vue
<style lang="scss">
  @import '~assets/sass/main.scss';
</style>
```

```vue:index.vue
  <h2 class="subtitle fs42">
    nust-start project
  </h2>
```

# netlifyでサクッとアップロード

[Netlify](https://www.netlify.com/)

Netlifyについては下記が詳しい。

[高機能ホスティングサービスNetlifyについて調べて使ってみた](https://qiita.com/TakahiRoyte/items/b7c4d1581df1a17a93fb)

下記を参考にサクッと設定

[Nuxt.jsで作ったものをそこそこ簡単な方法で公開する](https://qiita.com/gupuru/items/e9746df176261afc3af2#netlify)

## netlifyのエラーでデプロイ失敗した(´・ω・｀)

bitbucket（非公開）で使用。
コミットしたら勝手にビルドしてくれるけどエラーは下記

```bash
Error running command: Build script returned non-zero exit code: 1
```

[Nuxt.JSをNetlifyで公開しようとするとビルドできない問題をなんとかする](https://qiita.com/sakapun/items/25d96f1ce1d76eeda603)を参考にnodeのバージョンを指定してみたり、
リポジトリを公開にしてみたけど同じエラーが出た。

nuxtの公式のissuesに行き着いて解決:sob:
https://github.com/nuxt/nuxt.js/issues/219#issuecomment-278494315

NetlifyのDeploy settingsを`npm run build && npm run generate`に変更したらビルドできた。

> Netlify is for static hosting so you need to generate your website with Nuxt.

Netlifyは静的なホスティングなので、Nuxtのビルドしないとだめよって。
これを読んで気づいたけど、gitignoreでdistがコミット対象から外されてたorz


## ブックマークに追加してchromeと独立してアプリとして動くか確認
こちらが丁寧にスクショで説明されてるので割愛
[Nuxt.js で作った静的サイトを PWA 化する](https://qiita.com/QUANON/items/880eaa43c1d2f55f5b4d)

# ルーティング

[nuxt公式：ルーティングの基礎](https://ja.nuxtjs.org/guide/routing/#%E3%83%AB%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%81%AE%E5%9F%BA%E7%A4%8E)

ルーティングは設定なしでできた。

```
pages/
--| user/
-----| index.vue
--| index.vue
```

上記のようにuser/index.vueを追加して
http://localhost:3000/user
にアクセスするとできてたページができてた。すげえ。

# vuetifyとfont-awesomeを入れてみる

参考：[Nuxt.js で CSS フレームワークを 3 つ試した。](https://qiita.com/high-u/items/b8c708cd3795d2ab4a13)

## インストール
```bash
npm install --save @nuxtjs/vuetify
npm install --save @nuxtjs/font-awesome
```

## モジュールを追加

```javascript:nuxt.config.js
  modules: [
    '@nuxtjs/vuetify',
    '@nuxtjs/font-awesome'
  ]
```

## [vuetifyjs公式](https://vuetifyjs.com/ja/getting-started/quick-start)を参考に使えるようにしてみる

```vue:default.vue
<template>
  <div id="app">
    <v-app>
      <my-header />
      <nuxt />
      <my-footer />
    </v-app>
  </div>
</template>
```

## [vuetifyjs公式→UI componentにフッター](https://vuetifyjs.com/ja/components/footer)の例があったので入れてみる

```vue:footer.vue
<template>
  <v-footer height="auto">
    <v-card
      flat
      tile
      class="indigo lighten-1 white--text text-xs-center"
    >
      <v-card-text>
        <v-btn
          v-for="icon in icons"
          :key="icon"
          icon
          class="mx-3 white--text"
        >
          <v-icon size="24px">{{ icon }}</v-icon>
        </v-btn>
      </v-card-text>
      <v-card-text class="white--text pt-0">
        Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
      </v-card-text>
      <v-card-text class="white--text">
        &copy;2018 — <strong>Vuetify</strong>
      </v-card-text>
    </v-card>
  </v-footer>
</template>
<script>
export default {
  name: 'Footer',
  data: () => ({
    icons: ['fab fa-facebook', 'fab fa-twitter', 'fab fa-google-plus', 'fab fa-instagram']
  })
}
</script>
```
## font-awesomeのiconがなんかイタリックになっちゃう
共通scssに下記を追記して~~ごまかした~~修正してみた

```scss:common.scss
.icon {
  &:before {
    font-family: FontAwesome;
    font-style: normal;
  }
}
```

## iconにリンクがつけれるようにしてみる

```vue:footer.vue
<template>
  <v-footer height="auto">
    <v-card
      flat
      tile
      class="indigo lighten-1 white--text text-xs-center"
    >
      <v-card-text>
        <v-btn
          v-for="icon in icons"
          :key="icon.id"
          icon
          class="mx-3 white--text"
          v-bind:to="icon.url" // 追加
        >
          <v-icon size="24px">{{ icon.name }}</v-icon> // 名前を呼び出す
        </v-btn>
      </v-card-text>
      <v-card-text class="white--text pt-0">
        Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
      </v-card-text>
      <v-card-text class="white--text">
        &copy;2018 — <strong>Vuetify</strong>
      </v-card-text>
    </v-card>
  </v-footer>
</template>
<script>
export default {
  name: 'Footer',
  data () {
    return {
      icons: [// 名前とurlを返すように修正
          { name: 'fab fa-facebook', url: '/' },
          { name: 'fab fa-twitter', url: '/user' },
          { name: 'fab fa-google-plus', url: '/' },
          { name: 'fab fa-instagram', url: '/user' },
        ]
    }
  }
}
</script>
```