Nuxt.jsとTypeScriptで開発環境を構築する
Nuxt.jsとTypeScriptを用いた開発が増えてきたので、自分なりの環境構築や開発の方法をまとめてみました。
前提
yarn -v
1.22.5
node -v
v14.16.1
最終的なpackage.jsonのdependenciesは
"dependencies": {
"@nuxtjs/axios": "^5.13.1",
"core-js": "^3.9.1",
"nuxt": "^2.15.3",
"nuxt-buefy": "^0.4.4",
"nuxt-typed-vuex": "^0.2.0"
},
です。
プロジェクトの作成
まず、以下のコマンドでNuxt.jsのプロジェクトを作成します。
yarn create nuxt-app <project-name>
オプションでいくつか質問されます。
今回は以下のように回答しました。
? Project name: app
? Programming language: TypeScript
? Package manager: Yarn
? UI framework: Buefy
? Nuxt.js modules: Axios - Promise based HTTP client
? Linting tools: ESLint, Prettier, Lint staged files, StyleLint
? Testing framework: Jest
? Rendering mode: Single Page App
? Deployment target: Static (Static/Jamstack hosting)
? Development tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Continuous integration: None
? Version control system: Git
ブラウザでの確認
以下のコマンドを用いることで、開発中の画面(http://localhost:3000/)をブラウザで確認できます。
yarn dev
ポイント
Can't create . because there's already a non-empty directory . existing in path.
プロジェクト作成時のコマンドの引数であるproject-name
は省略できますが、ディレクトリが空でない場合エラーが出るので注意が必要です。
「このページは動作していません」と表示される場合
server: {
host: '0.0.0.0',
}
Nuxt.jsのデフォルトではホストマシンからのみアクセス可能です。
外部からのアクセスを許容する場合は、上記のような設定が必要になります。
詳しくは公式ドキュメントのホストとポート番号を編集する
を参照してください。
TypeScriptをVue.jsで使用
Nuxt.jsでTypeScriptを使用する場合、セットアップはほぼ初期設定のみ(Programming languageの質問でTypeScriptを選択する)で大丈夫ですが、実際に開発を進める際にファイルの種類毎にお作法のようなものがあります。
ここでは、実際に使用する場合の参考コードを紹介します。
動作確認用のコードを含んでいるので、実際に使用する場合は適宜修正して利用してください。
コンポーネント
scriptタグのlang属性を指定し、Vue.extend
を使用することでTypeScriptを使用できるようになります。
<script lang="ts">
import Vue from 'vue'
import Card from '~/components/Card.vue'
export default Vue.extend({
components: {
Card,
},
mounted() {
//動作確認用、意味のないコード
const foo: string = ''
console.log(foo)
},
})
</script>
Options API
ちなみに、
export default Vue.extend({
としている箇所があります。
これはOptions APIの場合のTypeScript化になります。
Composition APIを使う場合などは公式ドキュメントご参照ください。
※公式ドキュメントによると、Options API、Composition API、Class APIの例があるのですが、Class APIがVue3系より廃止になるらしい?のと、私の好みでOptions APIを用いた例にしています。
vue-shim.d.ts
IDEを用いているとimport使用箇所で
Cannot find module '~/components/Card' or its corresponding type declarations.
とでていると思います。
その場合は、types/vue-shim.d.ts
を作成し
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}
importの該当箇所で.vue
とすればエラーは消えます。
import Card from '~/components/Card.vue'
ただし、私の場合は後者の.vue
にするだけで大丈夫でしたので、より正確な対応方法があれば追記したいと思います。どなたか詳しい方は教えてください
参考
ミドルウェア
middleware/index.ts
等、任意のファイルを作成します。
import { Middleware, Context } from '@nuxt/types'
const test: Middleware = ({ isHMR }: Context) => {
//動作確認用、意味のないコード
console.log(isHMR)
}
export default test
そして、pages/index.vue
に以下を追加します。
もし、全ページに設定したい場合はpages/index.vue
ではなく、nuxt.config.js
に設定してください。
middleware: 'index',
ブラウザでconsoleにisHMR
の値を出力できたら成功です。
プラグイン
plugins/test.ts
等、任意のファイルを作成します。
import Vue from 'vue'
Vue.prototype.$test = (message: string) => console.log(message)
作成したプラグインに対する型定義ファイル(types/index.d.ts)を作成します。
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import Vue from 'vue'
declare module 'vue/types/vue' {
interface Vue {
$test(message: string): void
}
}
nuxt.config.js
で読み込む設定をします。
plugins: ['~/plugins/test.ts'],
実際にコンポーネントでプラグインを使用します。
mounted() {
this.$test('This is TypeScript test!!')
},
ブラウザでconsoleに文字を出力できたら成功です。
ストア
ここではOptions APIとの相性を考慮し、nuxt-typed-vuexを用いることにします。
yarn add nuxt-typed-vuex
nuxt.config.js
のbuildModulesにnuxt-typed-vuex
を追加します。
buildModules: [
'nuxt-typed-vuex',
],
store/index.ts
を作成します。
import { getAccessorType } from 'typed-vuex'
import * as submodule from '~/store/submodule'
export const state = () => {
return {}
}
export const getters = {}
export const mutations = {}
export const actions = {}
export const accessorType = getAccessorType({
state,
getters,
mutations,
actions,
modules: {
submodule,
},
})
store/submodule.ts
を作成します。
import { getterTree, mutationTree, actionTree } from 'typed-vuex'
export const state = () => ({
text: '' as string,
})
export const getters = getterTree(state, {
getText: (state) => state.text,
})
export const mutations = mutationTree(state, {
setText(state, newValue: string) {
state.text = newValue
},
})
export const actions = actionTree(
{ state, getters, mutations },
{
initialise({ commit }) {
commit('setText', 'typed-vuex test!!')
},
}
)
型定義ファイルであるtypes/index.d.ts
に追記し、以下のようにします。
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import Vue from 'vue'
import { accessorType } from '~/store'
declare module 'vue/types/vue' {
interface Vue {
$test(message: string): void
$accessor: typeof accessorType
}
}
declare module '@nuxt/types' {
interface NuxtAppOptions {
$accessor: typeof accessorType
}
}
これでコンポーネントからthis.$accessor
でアクセスできます。
//actions
this.$accessor.submodule.initialise()
//getters
this.$accessor.submodule.getText
devtoolsにうまくstoreが表示されない場合
以下の対応で表示されるかもしれません。
1.Vue Devtoolsの歯車アイコンの設定タブを押下
2.New Vuex backendをEnableに変更
参考:fix: devtools does not show auth module #108
さいごに
自身の備忘録を兼ねて作成しました。
参考になれば幸いです。
参考
文中にあげたリンク以外にも、以下のドキュメントを参考にさせていただきました。
Discussion