17
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【備忘録】Nuxt.jsをtypescript化してみた

Last updated at Posted at 2019-08-08

はじめに

nuxt.jsでプロダクト開発をしていて流石にjsが厳しくなってきたので、typescript版Nuxt.jsの雛形を作りました。
備忘録的に作業を記録しておきます。

nuxt.jsの雛形作成

$ yarn create nuxt-app <プロジェクト名/今回はnuxt-tsとしました>

create-nuxt-app v2.9.2
✨  Generating Nuxt.js project in nuxt-ts/
? Project name nuxt-ts
? Project description My geometric Nuxt.js project
? Author name taro
? Choose the package manager Yarn
? Choose UI framework None
? Choose custom server framework None (Recommended)
? Choose Nuxt.js modules (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Choose linting tools (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Choose test framework Jest
? Choose rendering mode Universal (SSR)

$ cd nuxt-ts

typescript化

公式ドキュメントでも推奨されていたのでnuxt-property-decoratorを採用。

$ yarn add -D @nuxt/typescript
$ yarn add ts-node nuxt-property-decorator
$ touch tsconfig.json
$ mv nuxt.config.js nuxt.config.ts

各種ファイルを変更

pages/index.vue
-<script>
-import Logo from '~/components/Logo.vue'
+<script lang="ts">
+import { Component, Vue } from "nuxt-property-decorator";

-export default {
+@Component({
   components: {
-    Logo
+    Logo: () => import("~/components/Logo.vue")
   }
-}
+})
+export default class IndexPage extends Vue {}
 </script>
components/Logo.vue
+<script lang="ts">
+import { Vue } from "nuxt-property-decorator";
+export default Vue.extend({})
+</script>

起動して確認。以外にあっさり完了しました^^

$ yarn dev

Vuexのtypescript化

続いてVuexです。
vuex-module-decoratorsを採用しました。(考察あり後述)

$ yarn add vuex-module-decorators
store/index.ts
import Vuex, { Store } from "vuex";

interface RootState {}
export const store = new Vuex.Store<RootState>({
  actions: {
    nuxtServerInit: () => {}
  }
});
const createStore = (): Store<RootState> => {
  return store;
};
export default createStore;

参考までにvuex-module-decoratorsを使うとこんな感じで書けます。

store/pages/index.ts
import { Mutation, Action, VuexModule, getModule, Module} from "vuex-module-decorators";
import { store } from "~/store";

interface IndexPageState {
  name: string;
}

@Module({ dynamic: true, store, name: "IndexPage", namespaced: true })
class IndexPage extends VuexModule implements IndexPageState {
  // state
  name: string = "";

  // mutations
  @Mutation
  private SET_NAME(name: string) {
    this.name = name;
  }

  // getters
  get name() {
    if (this.user == null) return "null";
    return this.user.name;
  }

  // actions
  @Action({})
  public fetch() {
    this.SET_NAME('hoge');
  }
}
export default getModule(IndexPage);

componentからはこのように使います。

pages/index.ts
<template>
  <div class="container">
    <p @click="test">{{ name }}</p>
  </div>
</template>

<script lang="ts">
import { Component, Emit, Vue } from "nuxt-property-decorator";
import PageStore from "~/store/pages/index";

@Component({
  async asyncData() {
    await PageStore.fetch();
  }
})
export default class IndexPage extends Vue {
  get name(): string {
    return PageStore.name;
  }

  @Emit()
  private test() {
    console.log(`test -> ${PageStore.name}`);
  }
}
</script>

これでVSCodeでインテンスも効いて快適になりました。
こちらの記事を参考にさせていただきました。ありがとうございます。

これで一件落着と思いきや、ここで1つ問題発生です。
vuex-module-decoratorsを採用したことでstoreをクラシックモードで記述することになります。
しかし、Nuxtのv3ではクラシックモードのサポートが切れるようなのでどうしたもんかなと...
以下のようなwarningが出ます。

 WARN  Classic mode for store/ is deprecated and will be removed in Nuxt 3.

この件についてこちらでも議論されていました。

今後はvuex-ormを使うのが良さそうと言う話ですが、
まだキャッチアップできてないので調べたら記事にしようと思います。
SSRでの実装方法もこちらに例がありましたので貼っておきます。

Eslint/Pretter

とりあえず一通りtypescript化できたので、次はEslitの設定を諸々進めます。

.eslintrc.js
module.exports = {
  root: true,
  env: {
    browser: true,
    node: true
  },
  parserOptions: {
    parser: '@typescript-eslint/parser',
    sourceType: 'module',
    project: './tsconfig.json',
    ecmaFeatures: { "legacyDecorators": true }
  },
  extends: [
    '@nuxtjs',
    'plugin:nuxt/recommended',
    'plugin:prettier/recommended',
    'prettier/vue',
    'prettier/@typescript-eslint'
  ],
  plugins: [
    'prettier',
    '@typescript-eslint'
  ],
  // add your custom rules here
  rules: {
    "no-unused-vars": "off",
    "@typescript-eslint/no-unused-vars": "error"
  }
}

上記に必要なパッケージ群をインストール

$ yarn add -D eslint@5.15.1 // eslintだけうまく入らなかったのでversion指定してあげました
$ yarn add -D eslint-plugin-nuxt @nuxtjs/eslint-config @typescript-eslint/parser @typescript-eslint/eslint-plugin prettier eslint-config-prettier eslint-plugin-prettier

eslintのaliasを設定

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

実行!

$ yarn lint --fix

まとめ

storeのクラシックモード問題があったり、まだまだ覚束無い感じですがtypescript化出来ました。
Vuex周りで何かいい解決方法お持ちの方いたら教えてくださいmm

備忘録で説明適当だったので、作業リポジトリのリンクを貼っておきます。
興味ある方はこちらからご覧ください。

では。

17
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?