create-nuxt-app で作った Nuxt.js プロジェクトで TypeScript を使うためにやったこと

先日 Nuxt.js の v.2.4.0 がリリースされました。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">Nuxt v2.4.0 is finally here 🎉<br>Official TypeScript support, smart prefetching and many more features &amp; bug fixes.<a href="https://t.co/Ljf29xYvXi">https://t.co/Ljf29xYvXi</a></p>&mdash; Nuxt.js (@nuxt_js) <a href="https://twitter.com/nuxt_js/status/1089948593392365568?ref_src=twsrc%5Etfw">2019年1月28日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

アップデートとして  大きな内容は `TypeScript公式対応` と `スマートプリフェッチ` でしょうか。
詳しくは dev.to の以下の公式ページの方に書かれています。（英語ですが・・・）
https://dev.to/nuxt/nuxtjs-v240-is-out-typescript-smart-prefetching-and-more-18d

@soichiro_nitta さんが Qiita の記事でわかりやすくまとめてくれていますので、詳しくはそちらを参考にしてください。
https://qiita.com/soichiro_nitta/items/d13ac10f9fdce022989d

## create-nuxt-app ではまだ v.2.4.0 未対応

2019/2/2 時点では `create-nuxt-app` で作成したプロジェクトでは `v.2.3.4` のままでした。
おそらくそのうち対応されるかと思いますが 、

**「Nuxt.js v2.4.0 触りたいけど、もう俺は TypeScript じゃないと JavaScript は書きたくないんや！」**

という人も多いはず！

ということで `create-nuxt-app` で作ったプロジェクトで TypeScript を使うためにやったことをまとめました。

## TypeScript は `nuxt-ts` というパッケージで対応してる

TypeScript に対応された Nuxt.js のパッケージは `nuxt-ts` という別名のパッケージで配布されています。

`create-nuxt-app` で作ったプロジェクトでは `nuxt` がインストールされてしまうので、
`nuxt-ts` を使用するようにインストールを進めていきます。

### まずは Nuxt.js のプロジェクトを作成する

- `npm init` を実行して `package.json` を作成します。
- `npm install -D create-nuxt-app` を実行して `create-nuxt-app` をインストールします。
- `npx create-nuxt-app` を実行して Nuxt.js プロジェクトの雛形を作成します。

この段階でインストールされている nuxt.js のバージョンは `2.3.4` のままです。
ここから v2.4 系にアップデートをしていきます。

### ここからが Nuxt.js 2.4 系へのアップデート手順

#### 1. ロックファイルと `node_modules` 配下をすべて破棄

- `rm -rf node_modules package-lock.json` を実行します。

#### 2. package.json の一部を変更

- dependencies から `nuxtを削除`します。
- `npm install -S nuxt-ts vue-property-decorator` を実行して `nuxt-ts` と `vue-property-decorator` インストールします。
  - vue-property-decorator を入れると、vue コンポーネントの定義を `@Component` などのデコレータを使って定義できるようになります。

#### 3. パッケージを更新できるものはすべて更新する

- `ncu -a` を実行します。
  - `ncu` コマンドが使えない場合は、 `npm-check-updates` をインストールしておく
  - インストール手順と使い方は以下を参照
  - [GitHub - tjunnone/npm-check-updates: Find newer versions of package dependencies than what your package.json or bower.json allows](https://github.com/tjunnone/npm-check-updates)

#### 4. 型定義ファイルの追加

- `typesync` を実行します。
  - `typesync` が使えない場合は `npm install -g typesync` でインストールしておく
  - `typesync` を実行すると package.json を参照して必要な `@types` をピックアップして package.json に追記してくれるらしいです。便利ですね！

#### 5. パッケージをインストール

- `npm install` を実行してパッケージをインストールします。

#### 6. package.json の scripts を修正

- コマンドで `nuxt` となっているところを `nuxt-ts` に変更します。

#### 7 TypeScript で適当なコンポーネントを作る

とりあえず、 `components` 配下に `HelloWorld.vue` というのを作ります。

<img width="293" alt="スクリーンショット 2019-02-02 15.29.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/61548/840fd5ae-0cf7-e95b-14f6-18ebee590376.png">

ソースの中身はこんな感じ。

「Hello world !」と表示するだけの簡単なやつです。

`<script lang="ts">` で宣言すると TypeScript として認識してくれます。

```HelloWorld.vue
<template>
  <div>
    {{ message }}
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'

@Component
export default class HelloWorld extends Vue {
  message: string = 'Hello world !'
}
</script>
```

それを `pages配下` の `index.vue` からマウントします。

```index.vue
<template>
  <section class="container">
    <div>
      <Logo />
      <HelloWorld />
    </div>
  </section>
</template>

<script>
import Logo from '~/components/Logo.vue'
import HelloWorld from '~/components/HelloWorld.vue'

export default {
  components: {
    Logo,
    HelloWorld
  }
}
</script>
```


#### 7 実行

- `npm run dev` を実行します。
- 「`tsconfig.json` が無いから作成しますか？」的なことを聞いてくるので Yes と答えます。
  - すると必要な情報が記載された `tsconfig.json` が  作成されます。

そしてコンパイル処理が進んでいくと・・・

怒られました。😓😓😓

<img width="1022" alt="スクリーンショット 2019-02-02 15.38.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/61548/604413bf-6f5a-2270-b9d5-534b5a820835.png">


#### 8 tsconfig.json の設定を修正

- 作成された `tsconfig.json` の compilerOptions に以下を設定を追加します。

```
"experimentalDecorators": true,
"allowJs": true,
```

``` tsconfig.json
{
  "extends": "@nuxt/typescript",
  "compilerOptions": {
    "baseUrl": ".",
+   "experimentalDecorators": true,
+   "allowJs": true,
    "types": ["@types/node", "@nuxt/vue-app"]
  }
}

```

上記を追記することで、2 で追加した `decorator` のコンパイルが可能になります。

#### 9 再び実行

- `npm run dev` を実行します。

今度はコンパイル通りました！🎉
<img width="420" alt="スクリーンショット 2019-02-02 15.54.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/61548/4c9e167d-48fe-0517-c197-926345a5dd47.png">

画面にも表示されました。🎉
<img width="402" alt="スクリーンショット 2019-02-02 15.59.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/61548/6bd3dda1-1429-8083-d851-80dc9a8b1f5b.png">


これで、コンポーネント作る時や内部処理を実装するときにTypeScriptを使えるようになりました👏👏👏