CloudFunction と React で共通のコードを読み込んで TypeScript でうまくコンパイルする方法
爆速でウェブアプリを公開する方法(無料でSSL独自ドメイン) で、Firebase / CloudFunction / TypeScript / React で開発する方法書いたけど、CloudFunction と React プロジェクトで共通のコードを使用したい場合にハマったので書いておく。
共通で使いたいのはモデル。
CloudFunction と React で共通で使いたいモデルを models/
に定義している。
1
2
3
4
5
6
- functions
- lib # CloudFunction のビルド先
- src # CloudFunction
- build # React のビルド先
- src # React
- models # 共通モデル
/src/models/*.js
として React の src 内に配置しているので、
Reactのビルドは問題なく通る。
ところが、TypeScript でコンパイルしてみると、
ディレクトリ階層が以下のようになってしまった。
1
2
3
4
5
6
7
8
9
- functions
package.json
- src // ソース
- lib // 出力
- functions
- src
- index.js
- models
- *.js // モデルファイル
lib
はコンパイル後のコードが出力される場所。 tsconfig.json の outDir で定義されている。
で、 functions/package.json
て定義されているこのプロジェクト(CloudFunctionの方)は、 lib/index.js
。
ところが出力された index.js のディレクトリ階層が異なってしまっている。
package.json の指定を変更すれば良いのかと思い、
やってみたが yarn serve
したときにパッケージが見つからないとエラーが出てしまった。
1
2
⚠ functions: Failed to load functions source code. Ensure that you have the latest SDK by running npm i --save firebase-functions inside the functions directory.
⚠ functions: Error from emulator. Error parsing triggers: Cannot find module '/Users/shunwitter/Dev/prj/functions'
node_modules
がどこにいるかわからない様子。
https://www.typescriptlang.org/docs/handbook/module-resolution.html こちらを読んでみたが、
これは TypeScript がどうやってモジュールをリゾルブするかの話なので関係なかった。そりゃそうだ。
ちなみに tsconf.json の rootDir
と rootDirs
はまったく違うオプションなので気をつけて。
https://github.com/Microsoft/TypeScript/issues/8245
にしても package.json と同階層に node_modules あれば、サブディレクトリのどこから読んでもリゾルブしてくれそうなもんだけど実際にはそうならず、1階層だけのジャンプアップならうまくいった。
以下のような構造。
1
2
3
4
5
- functions
- lib
- index.js
- node_modules
- ...
プロジェクト外のディレクトリを引っ張ってきているので、こんな事態になっているのだと思う。
ひとまずシンボリックリンクを配置すれば、ディレクトリ構造に問題はないし、コンパイル時にファイルをちゃんとコピーしてくれる。
CIとかで回す時どうするんだってのはあるが、その時は cp
でコピーしてしまえば良いのかな。
1
$ ln -s /path/to/your_project/src/models functions/src/models
それではー。
参考
TypeScript のモジュール読み込みについて TypeScript Module Resolution
tsconfig.json について TypeScript Compiler Options