はじめに
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
各種ファイルを変更
-<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>
+<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
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を使うとこんな感じで書けます。
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からはこのように使います。
<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の設定を諸々進めます。
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を設定
"scripts": {
+ "lint": "eslint --ext .ts,.js,.vue --ignore-path .gitignore ."
},
実行!
$ yarn lint --fix
まとめ
storeのクラシックモード問題があったり、まだまだ覚束無い感じですがtypescript化出来ました。
Vuex周りで何かいい解決方法お持ちの方いたら教えてくださいmm
備忘録で説明適当だったので、作業リポジトリのリンクを貼っておきます。
興味ある方はこちらからご覧ください。
では。