Featured image of post 【Nuxt.js】プロジェクトに後から自前でTypeScriptを導入する方法【yarnでサクッと簡単】

【Nuxt.js】プロジェクトに後から自前でTypeScriptを導入する方法【yarnでサクッと簡単】

1924文字

TypeScriptを導入しよう

Nuxt.jsを使ってアプリケーションを開発する際、TypeScriptを使った静的型付けを行うのが当たり前になってきています。

JavaScript that scales. TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.

Any browser. Any host. Any OS. Open source.

TypeScript - JavaScript that scales.

もちろん、Nuxt.jsはTypeScriptの導入についても手厚くサポートしています。

静的型付けは、とりわけアプリケーションが大きく成長したするにつれて、多くの潜在的なランタイムエラーを防ぐのに役立ちます。

それこそが Nuxt の新しい @nuxt/typescript パッケージがビルトインで TypeScript ツールをサポートする理由です:TypeScript サポート - Nuxt.js

今回も自前でTypeScriptを導入してみましたので、手順をご紹介致します。

手順

前提

Typescriptを導入した際に、lint周りで以下のようなエラーログが出るようになりました。

謎のエラー
ERROR  Failed to compile with 1 errors                                                                                           friendly-errors 08:56:17

Module build failed (from ./node_modules/eslint-loader/index.js):                                                                 friendly-errors 08:56:17
Error: Failed to load plugin @typescript-eslint: Cannot find module 'eslint-plugin-@typescript-eslint'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:581:15)
    at Function.resolve (internal/modules/cjs/helpers.js:30:19)
    at Plugins.load (/projects/sample/node_modules/eslint/lib/config/plugins.js:106:29)
    at Array.forEach (<anonymous>)
    at Plugins.loadAll (/projects/sample/node_modules/eslint/lib/config/plugins.js:166:21)
    at loadFromDisk (/projects/sample/node_modules/eslint/lib/config/config-file.js:501:35)
    at Object.load (/projects/sample/node_modules/eslint/lib/config/config-file.js:559:20)
    at Config.getLocalConfigHierarchy (/projects/sample/node_modules/eslint/lib/config.js:227:44)
    at Config.getConfigHierarchy (/projects/sample/node_modules/eslint/lib/config.js:179:43)
    at Config.getConfigVector (/projects/sample/node_modules/eslint/lib/config.js:286:21)
    at Config.getConfig (/projects/sample/node_modules/eslint/lib/config.js:329:29)
    at processText (/projects/sample/node_modules/eslint/lib/cli-engine.js:163:33)
    at CLIEngine.executeOnText (/projects/sample/node_modules/eslint/lib/cli-engine.js:620:17)
    at lint (/projects/sample/node_modules/eslint-loader/index.js:263:17)
    at Object.module.exports (/projects/sample/node_modules/eslint-loader/index.js:258:21)
                                                                                                                                  friendly-errors 08:56:17
You may use special comments to disable some warnings.                                                                            friendly-errors 08:56:17
Use // eslint-disable-next-line to ignore the next line.                                                                          friendly-errors 08:56:17
Use /* eslint-disable */ to ignore all warnings in a file.

ちょっと調べてみましたが、いまいち原因が分からなかったので、一旦ビルド時のlint関連を無効にする事で動作確認をとっています。orz

Failed to load plugin @typescript-eslint: Cannot find module 'eslint-plugin-@typescript-eslint'webpack - Failed to load plugin @typescript-eslint: Cannot find module 'eslint-plugin-@typescript-eslint' - Stack Overflow

Nuxt.jsにlintを入れるところは改めて作業をして記事にまとめようと思っています。

モジュールのインストール

まずは関連するモジュールをインストールしていきましょう。

@nuxt/typescript

Nuxt.jsの公式TypeScript用のモジュールをインストールします。

yarn add -D @nuxt/typescript
yarn add v1.16.0
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
success Saved 36 new dependencies.
info Direct dependencies
└─ @nuxt/typescript@2.8.1
info All dependencies
...
()
...
Done in 112.12s.

ts-node

次に、ts-nodeをインストールします。

こちらは、typescriptのコードをコンパイルする事なく直接node上で実行してくれるものです。
自分でコンパイルする必要が無くなるのはデカイですね。

yarn add ts-node
yarn add v1.16.0
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved 1 new dependency.
info Direct dependencies
└─ ts-node@8.2.0
info All dependencies
└─ ts-node@8.2.0
Done in 111.66s.

vue-property-decorator

次は、vue-property-decoratorです。

こちらはVueの記述をデコレーターを使って記述できるようにしてくれるものです

yarn add -D vue-property-decorator
yarn add v1.16.0
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved 1 new dependency.
info Direct dependencies
└─ vue-property-decorator@8.1.1
info All dependencies
├─ vue-class-component@7.1.0
└─ vue-property-decorator@8.1.1
Done in 112.44s.

ファイルのTypeScript対応

では、次に既存のファイルをTypeScript化していきましょう。

nuxt.config.js

nuxt.config.jsnuxt.config.tsとリネームしましょう。
ファイルの中身はそのままで問題ありません。

tsconfig.json

次にtouch tsconfig.jsonでファイルを作成しましょう。
こちらのファイルの内容は起動時に自動で記述されるので空の状態で問題ありません。

pages/index.js

次に、index.jsindex.tsにリネームした上で内容を変えていきましょう。

(修正前)pages/index.js
import AppLogo from '~/components/AppLogo.vue'

export default {
  components: {
    AppLogo
  },
  async asyncData () {
    let hoge = "fuga"
    let data = { hoge }
    return {
      data
    }
  }

}

(修正後)pages/index.ts
import { Component, Vue, Prop } from 'vue-property-decorator'

@Component({
  components: {
    AppLogo: () => import('~/components/AppLogo.vue')
  },
  async asyncData () {
    let hoge = "fuga"
    let data = { hoge }
    return {
      data
    }
  }
})
export default class Index extends Vue {}

pages/index.vue

次にpages/index.vueを修正しましょう。

pages/index.vue
<template lang="pug" src="./index.pug" />
<script src="./index.ts" lang="ts" /> // 属性を追加し、読み込みファイルをindex.tsに修正
<style lang="scss" scoped src="./index.scss" />

確認

これでTypeScript化の準備は出来たので、実際に確認してみましょう。

yarn dev
yarn run v1.16.0
$ nuxt

   ╭─────────────────────────────────────────────╮
   │                                             │
   │   Nuxt.js v2.8.1                            │
   │   Running in development mode (universal)   │   TypeScript support is enabled             │
   │                                             │
   │   Listening on: http://172.25.0.2:3000/     │
   │                                             │
   ╰─────────────────────────────────────────────╯

ℹ Preparing project for development                                                                                                               10:37:49
ℹ Initial build may take a while                                                                                                                  10:37:49
✔ Builder initialized                                                                                                                             10:37:49
✔ Nuxt files generated                                                                                                                            10:37:49
ℹ Starting type checking service...                                                                                                               10:37:59
ℹ Using 1 worker with 2048MB memory limit                                                                                                         10:37:59

✔ Client
  Compiled successfully in 38.10s

✔ Server
  Compiled successfully in 34.73s

ℹ No type errors found                                                                                                                            10:38:37
ℹ Version: typescript 3.5.2                                                                                                                       10:38:37
ℹ Time: 34162ms                                                                                                                                   10:38:37
ℹ Waiting for file changes                                                                                                                        10:38:38
ℹ Memory usage: 193 MB (RSS: 297 MB)

起動ログに、TypeScript support is enabledが追加され、No type errors foundが出力されたので正常に起動しましたね♪

記述エラー時

試しに以下のようなエラーが発生する状態(String型の変数に数値を代入)にソースを変えると、、、

pages/index.ts
import { Component, Vue, Prop } from 'vue-property-decorator'

@Component({
  components: {
    AppLogo: () => import('~/components/AppLogo.vue')
  },
  async asyncData () {
    let hoge = "fuga"
    hoge = 1 // TypeScriptエラー
    let data = { hoge }
    return {
      data
    }
  }
})
export default class Index extends Vue {}

ビルドエラー
ℹ Type checking in progress...                                                                                                                    10:42:43

 ERROR  ERROR in /projects/sample/pages/index.ts                                                                                                  10:42:46
9:5 Type '1' is not assignable to type 'string'.
     7 |   async asyncData () {
     8 |     let hoge = "fuga"
  >  9 |     hoge = 1
       |     ^
    10 |     let data = { hoge }
    11 |     return {
    12 |       data

ℹ Version: typescript 3.5.2                                                                                                                       10:42:47
ℹ Time: 4091ms

期待通りチェックしてくれるようになりましたね♪

tsconfig.jsonの内容

tsconfig.jsonは以下のような記述が生成されています。

tsconfig.json
{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "lib": [
      "esnext",
      "esnext.asynciterable",
      "dom"
    ],
    "esModuleInterop": true,
    "experimentalDecorators": true,
    "allowJs": true,
    "sourceMap": true,
    "strict": true,
    "noImplicitAny": false,
    "noEmit": true,
    "baseUrl": ".",
    "paths": {
      "~/*": [
        "./*"
      ],
      "@/*": [
        "./*"
      ]
    },
    "types": [
      "@types/node",
      "@nuxt/vue-app"
    ]
  }
}

終わりに

以上のように、Nuxt.jsのTypeScript化についても依存関係を追加することで簡単に実現することが出来ました。

JavaScriptを使ったフロントエンドの開発においては、TypeScriptはほぼマストの技術となっていますので、是非試してみてください♪