CloudFunction と React で共通のコードを読み込んで TypeScript でうまくコンパイルする方法

Shunsuke Sawada

爆速でウェブアプリを公開する方法(無料で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 の rootDirrootDirs はまったく違うオプションなので気をつけて。
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

Shunsuke Sawada

おすすめの記事

SlackのOAuthを使って独自アプリをインストールさせる
1
爆速でウェブアプリを公開する方法(無料でSSL独自ドメイン)/ React + Typescript + Cloud Function + Firebase Hosting
2