NuxtJSのTypescript環境構築!Typescriptによる堅牢なフロントエンド開発環境構築を解説します😎

NuxtJSのTypescript環境構築!Typescriptによる堅牢なフロントエンド開発環境構築を解説します😎

こんにちは!

最近ではフロントエンドを Typescript で実装するケースが非常に増えてきました。Typescript を使用することで、複雑になりやすいフロントエンド開発を安全・堅牢に実装することが可能になります。

加えて、Amplify を使用した graphql 実装を行う際、schema.graphql のデータ定義から自動的に API の型情報を生成することができるため、graphql 開発とも相性が良いと言えます。

読者の皆さんも本記事を参考にしていただき、NuxtJS の Typescript にチャレンジしてみてください!

はじめに

本記事は「NuxtJS の Typescript 環境構築方法」について解説しますので、Typescript の詳しい実装内容には触れていません。

また、本記事は NuxtJS 環境への Typescript 環境構築方法について重点的に解説するため、非 Typescript の NuxtJS 環境への Typescript 設定方法の解説をいたします。

想定する読者

  • フロントエンドを Typescript で実装してみたいヒト
  • Typescript 実装経験のあるヒト
  • NuxtJS または NextJS でフロントエンドを開発しているヒト

NuxtJS の Typescript 環境構築

1. Typescript ビルド用パッケージインストール

Typescript のビルドに必要なパッケージをインストールします。インストールしたパッケージは、「nuxt.config.js」へ設定(後述)します。

yarn add --dev @nuxt/typescript-build @nuxt/types

2. nuxt.config.jsの設定

NuxtJS には Webpack が内包されています。その Webpack でビルドを行う際に Typescript 用のモジュールを指定します。これにより、Typescript のシンタックスを *.vue ファイル内で扱うことが可能となります。

/nuxt.config.js

export default {
  ...
  buildModules: ['@nuxt/typescript-build']
  ...
}

3. Typescript のビルド設定ファイルの作成

NuxtJS の buildModules に指定した Typescript のビルドモジュールが使用する設定ファイルをプロジェクトのルートディレクトリに作成します。

/tsconfig.json

{
  "compilerOptions": {
    "target": "ES2018",
    "module": "ESNext",
    "moduleResolution": "Node",
    "lib": [
      "ESNext",
      "ESNext.AsyncIterable",
      "DOM"
    ],
    "esModuleInterop": true,
    "allowJs": true,
    "sourceMap": true,
    "strict": true,
    "noEmit": true,
    "experimentalDecorators": true,
    "baseUrl": ".",
    "paths": {
      "~/*": [
        "./*"
      ],
      "@/*": [
        "./*"
      ]
    },
    "types": [
      "@types/node",
      "@nuxt/types",
      "node"
    ]
  },
  "exclude": [
    "node_modules",
    ".nuxt",
    "dist",
    "coverage"
  ],
}

4. eslint & prettierの設定

Typescript 用の Lint モジュールをインストールし、設定ファイルを作成します。

yarn add -D @nuxtjs/eslint-config-typescript eslint-plugin-prettier eslint-plugin-nuxt prettier eslint-config-prettier

/.eslintrc.yml(好みで json にしてください)

root: true
env:
  browser: true
  node: true
extends:
    - '@nuxtjs'
    - '@nuxtjs/eslint-config-typescript'
    - 'plugin:prettier/recommended'
    - 'plugin:nuxt/recommended'

/.prettierrc

{
  "semi": false,
  "singleQuote": true
}

/ nuxt.config.js

export default {  
  ...
  typescript: {
    typeCheck: {
      eslint: {
        files: './**/*.{ts,vue}',
      },
    },
  }
  ...
}

エディターが WebStorm( JetBrains 系)の場合は、ファイル保存時に自動実行を設定しておきましょう。

ESLint の自動実行
Prettier の自動実行

これで基本的な設定は完了です!

次は、私たちが普段採用している Typescript 環境のカスタム内容をご紹介します👍

vue-property-decorator でVueファイルの Typescript を class 化

Vue ファイルで Typescript を扱う場合、5つのシンタックスを選択することができます。

  • Vue.component
  • Class-Style Vue Components
  • Augmenting Types for Use with Plugins
  • Annotating Return Types
  • Annotating Props

私たちは、State への型をつけやすさ・保守性の高さから、上記のうち Class-Style Vue Components を使用し実装を行っています。(後述)どれが正解ということもないので、好みの方法で実装を行ってください。

Vue に慣れているエンジニアが多数いるのであれば、癖のない Vue.component を使用するのも一つだろうと感じます。詳しくは公式をご覧ください。

以下に Class-Style Vue Components による Vue ファイル実装例をご紹介します。

Class-Style Vue Components による Class 型実装

yarn add -D vue-property-decorator

/pages/products.vue

import { Component, Vue } from 'vue-property-decorator';

type Product = {
  id: string
  name: string
  price: number
}

@Component({
  middleware: ['withMiddleware'], // middlewareを使用したい場合に設定
  head() {
    return {
      title: '商品一覧',
    }
  },
})
export default class SampleComponent extends Vue {
  // state
  products: Product[] = []

  // computed
  get getProducts() {
    return this.products;
  }

  mounted(){
    this.fetchProducts() 
  }

  // methods内に設定する関数
  onClickProduct(product:Product){
    alert(product)
  }

  // methods内に設定する関数
  fetchProducts(){
    // 商品取得処理情報取得処理
    this.products = [
      {
        id: 1,
        name: "イヤホン",
        price: 5980,
      },
      {
        id: 2,
        name: "ドライヤー",
        price: 9250,
      }
    ];
  }
}

Vue を都度 import したくない場合、以下のように Typescript にグローバルにVue を宣言することを検討してみてください。

/global.d.ts

declare module '*.vue' {
  import Vue from 'vue'
  export default Vue
}

vuex-module-decorators で Store のTypescript を class 化

最後に、Store を Class 化する手順を紹介します。Store も Vue ファイル同様複数実装パターンがありますが、私たちはプロジェクトに応じて以下の2パターンを使い分けています。

  • vuex
  • vuex-module-decorators

vuex(Basic typing

従来の Vuex を TS 実装したパターンです。もともと Vue 実装に慣れている方は馴染みやすいかなと感じます。既存の Vue プロジェクトを移行する必要がある場合は、こちらを採用することがしばしばあります。

import { GetterTree, ActionTree, MutationTree } from 'vuex'

export const state = () => ({
  things: [] as string[],
  name: 'Me',
})

export type RootState = ReturnType<typeof state>

export const getters: GetterTree<RootState, RootState> = {
  name: state => state.name,
}

export const mutations: MutationTree<RootState> = {
  CHANGE_NAME: (state, newName: string) => (state.name = newName),
}

export const actions: ActionTree<RootState, RootState> = {
  async fetchThings({ commit }) {
    const things = await this.$axios.$get('/things')
    console.log(things)
    commit('CHANGE_NAME', 'New name')
  },
}

vuex-module-decorators を使用した Class 型実装

Vue ファイルを Class で実装するなら、全体的に統一感が出るためこちらの Class 型の実装を推奨します。アノテーションを使用し、Class 内のメンバーにオプションを付与します。私たちは保守性の高さからこちらの実装パターンを推奨しています。

yarn add -D vuex-module-decorators
import { Module, VuexModule, Action, Mutation } from 'vuex-module-decorators'
import { $axios } from '~/utils/api'
import { Product } from '~/types'

@Module({
  name: 'products',
  stateFactory: true,
  namespaced: true,
})
class ProductModule extends VuexModule {
  products: Product[] = []

  @Mutation
  setProducts(products: Product[]) {
    this.products = products
  }

  @Action
  async getProducts() {
    const products = await $axios.$get('/products')
    this.setProducts(products)
  }
}

まとめ

NuxtJS・Vue で大規模開発を行うなら Typescript は必須と言えます。

ReactJS のような堅牢な JS 実装と、Vue ならではの美しい HTML を両方活かすことが可能となり、フロントエンドで高い開発効率を実現することができます。もしこれから新規開発のプロジェクトがあるなら、ぜひぜひ導入を検討してみてください!

フロントエンドの Typescript 開発は気軽に問い合わせください。