LoginSignup
3

More than 3 years have passed since last update.

posted at

updated at

NestJSアプリケーションのビルドサイズをncc使って300MB減らした話

Dockerイメージサイズをできるだけ小さくする際に試行錯誤した結果、nccを使ってイメージサイズを減らせたので備忘録

ncc使う前 ncc使った後 結果
599MB 245MB 354MB削減!

Image from Gyazo

ビルド手順

nccはTypeScriptをサポートしています。ですが、tsconfig.jsonの指定ができないためtsconfig.app.jsonのような複数の設定ファイルを保持している場合、うまく使用することができません。

そこで次の手順を踏みます。

例: apiというアプリをビルド
1. nest-cliでwebpackモードでビルドする: nest build api --webpack
2. 1の成果物をnccで更にビルドする ncc build dist/api.js -m -o dist/api

するとアプリに必要なファイルをまとめて出力してくれます。 Dockerイメージにはこれを含めればいいだけ。

Image from Gyazo

nccすごいですよ。webpackのやつを更にビルドできるの。

これにより、node_modulesが必要なくなり必要最低限のファイルのみがDockerイメージに含まれることになりました。
(node_modulesはもちろんnpm ci --productionでインストールしたもの)
Image from Gyazo

... attempted to require "@nestjs/microservices" but could not be resolved, assuming external.

(↑正確なエラー文忘れて記録にも残ってないので前半ぼかしてます...)

nccでビルドしたファイルを実行すると、@nestjs/microservices のインポートがうまく解決できないエラーが発生しました。関連issueはこちら: https://github.com/zeit/ncc/issues/463

私の場合、@nestjs/microservicesはメインで使っておらず@nestjs/terminusが動的に読み込みを行っているようです。terminusはヘルスチェックに必要ですが、少し前にサーバーレスに移行したため、重要度が低くなりました。なので@nestjs/terminus自体を削除しました。

nccの成果物にtypescriptが含まれる

場合によって、typescriptがまるっと含まれる可能性があります。47.8MB、めちゃくちゃでかい。当たり前なんですが、typescriptフォルダ自体削除しても特に動作に支障はありませんでした。
Image from Gyazo

え、300MBも削減されてんの?動くのこれ?という不安

Image from Gyazo

↑の結果を初めて見た時、かなり不安になりました。本当に最適化されただけ...?何か重要なファイル消えてない..?と言う感じで。
e2eテストをこのnccで行いましたが、ちゃんとテストは通っているので問題無しとしています(テスト書いててよかった)

あと、パッケージによっては古いバージョンのライブラリを参照してることがあります。バージョンの異なる同じパッケージが含まれているか調べましたが、ちゃんと含まれているようです(uuidのパッケージが4つも含まれてた...)。

更にpkgでシングルファイルにすれば完璧では...!?

alpine + pkg の組み合わせは動かなかった。static link周りでエラーが出る。
https://github.com/zeit/pkg-fetch/pull/72
そもそもpkgはサーバーレス用途では使わないでってREADMEに書いてあるし使うのは辞めた。
https://github.com/zeit/pkg/blob/master/README.md

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
3