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 の 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

何かありましたらコメントをどうぞ

comments powered by Disqus

人気の記事

950 Points チリ出身のギタリストが弾くドラゴンボールZがむちゃくちゃかっこいい…
774 Points Wordpress + Heroku + PostgreSQL + Amazon S3 = ¥0 / 無料でサイト運営
700 Points Rubyのチートシート 変数 / クラス / モジュール
524 Points Rubyのチートシート / アクティブサポート
451 Points 紙のデザイナーがウェブ開発できるようになるまでに必要なこと
435 Points Rails / Google Analyticsのデータを使って分析や管理画面のためのグラフをつくる
323 Points RailsとHerokuでノーティフィケーションをプッシュする / PusherとTurbolinksの兼ね合い
222 Points Rails / RSpec テスト書いたことない メンドクサイ(n´Д`)という時のチートシート
193 Points Rails / Ajaxを使って画面遷移しない一時保存機能をつける
193 Points Protractorでスクレイピングしてみた