tsconfig.json の extends の使い方
解決したい問題
今回お題にしているのは、Nuxtですが、それに限らないと思います。
アプリを作るにあたって、Nuxtでフロントエンドを作り、APIを作成して呼び出し、APIがDBの読み書きをする、という構成にすることが多いのではないかと思います。
そしてこの各サービスをまとめて開発する場合、それぞれをDockerイメージにしたい場合もあるのではないかと思います。
例えば、このような構成です。
XXXApp
├── docker-compose.yml
├── .git
├── .gitignore
├── README.md
├── xxx-app-api
│ ├── (Django REST)
│ ├── ...
├── xxx-app-db
│ ├── (postgres)
│ ├── ...
├── xxx-app-web
│ ├── (nuxt)
│ ├── ...
この構成を、まとめて開発するので、一つのVSCodeでXXXAppを開きたいと考えます。
そして、Nuxtについては、今時はやはりTypescriptで開発したいなと思います。
ところが、うまく参照ができない。
例えば、pages/todolist.vueというものを作って、
<script lang="ts">
import { defineComponent, reactive, computed } from '@vue/composition-api'
import { TodoStore } from '~/store'
・・・
const todos = TodoStore
const todolist = computed(() => todos.getTodos)
みたいに書く際に、getTodosで補完が効いて欲しいのですが、「from '~/store'」のところで、「Cannot find module」エラーと言われてしまうわけです。
これの解消に時間がかかりました。意外と、ズバッと教えてくれる情報がないなと。
構成に関わらず必須な作業
まず、shims-vue.d.ts の対応、tsconfig.json への「files」「include」対応は必要です。
例えば、下記の情報など参照。
Nuxt 2.8の生成するtsconfig.jsonを使うとIntelliJ(WebStorm、PhpStorm等)がCannot find moduleエラーを吐く
そして、元々記述はされていると思いますが、
"baseUrl": ".",
"paths": {
"~/*": [
"./*"
],
"@/*": [
"./*"
]
},
も必要です。
Typescriptプロジェクトが下位階層にある場合
ところが、最初に問題意識を書いたような階層構成の場合は、これだけでは足りません。
上記構成で言うと、VSCodeとしては、XXXApp が基礎となる位置になるわけで、そこに tsconfig.json はいません。アプリ動作のためには、xxx-app-web にいる必要があるのですが、VSCodeにとっては、XXXApp にいて欲しいわけです。
そこで、extends を使います。
・・・という情報までは辿り着きましたが、それの意味が理解できなかった。
{
"extends": "./poli-link-web/poli-link/tsconfig.json"
}
これだけ書いても、そのまま読み込むだけなので、その場所が基礎位置になるだけです。
そこに store はいません。
extends なので、それを読み込むだけではダメなのです。
そこから見た基礎位置を、baseUrl として指定します。
{
"extends": "./xxx-app-web/tsconfig.json",
"compilerOptions": {
"baseUrl": "./xxx-app-web",
}
}
これが必要です。これによって、VSCodeとしても位置が整合することになるので、import が正しく機能することになります。
分かってしまえば、当然だね、と思いますが、修行中の身には堪えました。
以上です。
Discussion