LoginSignup
3

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-03-19

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
  3. You can use dark theme
What you can do with signing up
3