lernaのpackageはsymbolic linkであることに注意したい

当記事は、半年以上前に投稿されたものです。そのため、古い技術や情報をもとに書かれている可能性があります。参照する際は十分に注意していただければです。

はじめに

先日、個人で開発している Lerna でモノレポ構成の子パッケージをデプロイしようとすると以下のように怒られました。

Error: Cannot find module '@hoge/graphql-schema'

エラー内容から、@hoge/graphql-schemaはありませんと言われたのです。

TL; DR

Lernaのモノレポ構成を採用していた場合、別パッケージの参照にはシンボリックリンクが貼られているため、パッケージ単体でデプロイした場合、シンボリックリンク故に実体のディレクトリ・ファイルが参照できなくなり、module がないよと怒られてしまいます。

なので、実体のファイルやディレクトリを用意してあげる必要があります。

内容

個人開発では、GraphQLでスキーマファースト、Lernaでモノレポ構成にしているため、graphql-schemaというパッケージに GraphQL のスキーマを記述しています。そして、バックエンドを記述するパッケージgraphqlではそのgraphql-schemaを npm モジュールとして参照するようにしています。

$ tree packages -L 1
packages
├── graphql # バックエンドが記述されているパッケージ
└── graphql-schema # Graphqlスキーマを記述しているパッケージ

2 directories, 0 files

そして、バックエンド API が固められたgraphqlパッケージを Lambda Container にデプロイしようとすると、上述のエラーが発生したのです。

最初は Lambda もしくはコンテナ内のファイル権限の問題かなと思いました。

ところが、module(package)がないよと言われているので、デプロイ image にgraphql-schemaディレクトリがまさか素直にないのかと思いlsしてみると、Symbolic Linkではないですか!

$ ls -la
total 0
drwxr-xr-x    3 smiler  staff    96  5 31 02:05 .
drwxr-xr-x  273 smiler  staff  8736  5 31 02:05 ..
lrwxr-xr-x    1 smiler  staff    23  5 31 02:05 graphql-schema -> ../../../graphql-schema

Lerna の README を眺めているとBootstrap時にPacakges配下はそれぞれSymlinkされると明示的に書かれていました。

  1. Symlink together all Lerna packages that are dependencies of each other. Lerna README bootstrap#usage より

よって、graphql-schemaを npm パッケージとしてインストールしていても Symbolic Link として参照されるため、graphqlパッケージのみをデプロイすると、実体としてgraphql-schemaがいないためCannot find moduleと怒られていました。

では、どう解消したかと言うと、全くナンセンスかと思いますが、デプロイ時にgraphql-schemaを明示的に node_modules 配下にコピーしてあげることで、実体として存在させ参照できるようにしました。

おわりに

bootstrap 時に実体としてファイル・ディレクトリをそもそも置けないのか?

バンドルすれば良いとも聞くのですが、どうするのだろうか…


Canji

クラウド周りをちょこまかしたい注意散漫人間。個人開発を楽しんでいたあの頃。