LoginSignup
14
10

Node.jsアプリケーションを単一exeファイルにする

Last updated at Posted at 2021-11-16

社内で NestJS を利用したアプリケーションを構築した後
exe ファイルへの変換と Windows サービスへの登録が必要になりました。

あまり情報がなかったので備忘録的に書き残します。

NestJS だけでなく Node.js を利用したアプリケーション全般に適用できる内容かと思います。

環境

  • Windows10 64bit
  • Node.js 14.18.1

NestJS とは(一応)

  • Node.js Web フレームワーク
  • TypeScript の完全なサポート
  • ORM(TypeORM, Sequelize)のサポート
  • GraphQL のサポート
  • Express を超える抽象化
  • Angular のアーキテクチャから影響を受けている
  • Guards を利用した認証
  • WebSockets のサポート

など…Express で後々必要になる機能が最初から用意されており、ドキュメントも充実しています。
なにより初学者は TypeScript の環境作成だけで苦労するので、最初から ts-node を利用した環境が用意されるのはありがたいです。
Module, Controller, Provider(Service)の概念を理解するのに少し苦労しますが Angular を使用したことがある方なら特に問題はないでしょう。

また、とっつきにくかった GraphQL をコードファーストで定義することができ、理解するのにとても役立ちました。
実装とスキーマ定義を同期させながら開発ができることも魅力でした。(一般的にはスキーマファーストで開発するのが主だとは思いますが)
例えば lerna + yarn workspaces + NestJS + NextJS の構成にしてフロント、バックエンドで同じスキーマ定義ファイルを参照し開発を進められます。

概要

簡単な NestJS プロジェクトの作成と exe ファイルへの変換の手順を示します。

プロジェクトの作成

Nest CLI をインストール

npm i -g @nestjs/cli

プロジェクトの作成

nest new <project-name>

パッケージマネージャの指定はお好みで。この時点でサーバーを立てられる状態になっています。

cd <project-name>
npm run start

http://localhost:3000/ に GET リクエストを投げれば Hello World! が返ってきます。

ビルド

npm run build

distフォルダに js ファイルが作成され、以下コマンドで起動できます。

node dist/main
# or "npm run start:prod"

この dist/main.js をエントリポイントとする exe ファイルの作成を行います。

nexe のインストール

nexe は Node.js アプリケーションを単一 exe ファイルにコンパイルしてくれるツールです。

同様なツールに pkg がありこちらの方が手軽だったのですがアイコンの変更やバージョン情報の書き換えを行うと起動できなくなったのでやめました。

NestJS プロジェクトの devDependencies に追加します。

npm i nexe --save-dev

exe ファイルの作成

以下コマンドを実行します。

./node_modules/.bin/nexe dist/main.js --target windows-x64-14.15.3 --output NestJS.exe

--target を省略すると Windows にインストールされている Node.js 環境のダウンロードを試みるのですが、https://github.com/nexe/nexe/releases にないバージョンだと

Error: https://github.com/nexe/nexe/releases/download/v3.3.3/windows-x64-14.18.1 is not available, create it using the --build flag

と表示されるので windows-x64-14.15.3 を直接指定しています。

アイコンの作成・変更

アイコンの作成

ImageMagickを使用してsvgファイルからicoファイルを作成します。

とりあえず NestJS アイコンsvgファイル を使用して icoファイルを作成することにします。

./magick.exe convert icon.svg -transparent white -define icon:auto-resize icon.ico

アイコンの削除

Resource Hacker を使用して初期アイコンを削除します。

./ResourceHacker.exe -open NestJS.exe -save NestJS.exe -action delete -mask ICONGROUP,1,1033
Current Directory:
D:\Node.js\Nest\executable

Commandline:
"D:\Node.js\Nest\executable\ResourceHacker.exe" -open NestJS.exe -save NestJS.exe -action delete -mask ICONGROUP,1,1033

Open    : D:\Node.js\Nest\executable\NestJS.exe
Save    : D:\Node.js\Nest\executable\NestJS.exe

  Deleted: ICONGROUP,1,1033

Success!

アイコンの追加

./ResourceHacker.exe -open NestJS.exe -save NestJS.exe -action addoverwrite -resource <ico FilePath> -mask ICONGROUP,MAINICON,0
Current Directory:
D:\Node.js\Nest\executable

Commandline:
"D:\Node.js\Nest\executable\ResourceHacker.exe" -open NestJS.exe -save NestJS.exe -action addoverwrite -resource icon.ico -mask ICONGROUP,MAINICON,0

Open    : D:\Node.js\Nest\executable\NestJS.exe
Save    : D:\Node.js\Nest\executable\NestJS.exe
Resource: D:\Node.js\Nest\executable\icon.ico

  Added: ICONGROUP,MAINICON,0

Success!

バージョン情報の編集

Rc ファイル作成

以下の内容のファイルを utf-16VersionInfo.rc として保存します。

VersionInfo.rc
1 VERSIONINFO
FILEVERSION 1,0,0,0
PRODUCTVERSION 1,0,0,0
FILEOS 0x4
FILETYPE 0x1
{
  BLOCK "StringFileInfo"
  {
    BLOCK "041103a4"
    {
      VALUE "CompanyName", "(C) xxx CORPORATION"
      VALUE "FileDescription", "NestJS"
      VALUE "FileVersion", "1.0.0.0"
      VALUE "InternalName", "NestJS.exe"
      VALUE "LegalCopyright", "(C) xxx CORPORATION"
      VALUE "OriginalFilename", "NestJS.exe"
      VALUE "PrivateBuild", "0000"
      VALUE "ProductName", "NestJS"
      VALUE "ProductVersion", "1.0.0.0"
      VALUE "SpecialBuild", "0000"
    }
  }
  BLOCK "VarFileInfo"
  {
    VALUE "Translation", 0x0411 0x03A4
  }
}

Res ファイル作成

./ResourceHacker.exe -open VersionInfo.rc -save VersionInfo.res -action compile
Current Directory:
D:\Node.js\Nest\executable

Commandline:
"D:\Node.js\Nest\executable\ResourceHacker.exe" -open VersionInfo.rc -save VersionInfo.res -action compile

Open    : D:\Node.js\Nest\executable\VersionInfo.rc
Save    : D:\Node.js\Nest\executable\VersionInfo.res

Compiling: D:\Node.js\Nest\executable\VersionInfo.rc
Success!

初期バージョン情報の削除

./ResourceHacker.exe -open NestJS.exe -save NestJS.exe -action delete -mask VERSIONINFO,1,1033
Current Directory:
D:\Node.js\Nest\executable

Commandline:
"D:\Node.js\Nest\executable\ResourceHacker.exe" -open NestJS.exe -save NestJS.exe -action delete -mask VERSIONINFO,1,1033

Open    : D:\Node.js\Nest\executable\NestJS.exe
Save    : D:\Node.js\Nest\executable\NestJS.exe

  Deleted: VERSIONINFO,1,1033

Success!

バージョン情報の追加

./ResourceHacker.exe -open NestJS.exe -save NestJS.exe -action addoverwrite -resource VersionInfo.res
Current Directory:
D:\Node.js\Nest\executable

Commandline:
"D:\Node.js\Nest\executable\ResourceHacker.exe" -open NestJS.exe -save NestJS.exe -action addoverwrite -resource VersionInfo.res

Open    : D:\Node.js\Nest\executable\NestJS.exe
Save    : D:\Node.js\Nest\executable\NestJS.exe
Resource: D:\Node.js\Nest\executable\VersionInfo.res

  Added: VERSIONINFO,1,1041

これでアイコンとバージョン情報を設定した exe ファイルが作成できました。

もし.env など参照ファイルがあれば exe ファイルと同じ場所に配置してください。

モジュールが見つからないとエラーが表示された場合は、該当のモジュールのみ含む node_module フォルダを作成して exe ファイルと同じ場所に配置してください。

Cannot find module 'xxx' or its corresponding type declarations.

Windows サービスへの登録

NSSM を使用し、作成した exe ファイルを Windows サービスとして登録します。
使い方は公式を参照すれば問題ないと思いますが、管理者権限が必要なことに注意してください。

サービスへの登録はこんな感じ。

./nssm.exe install NestJSService NestJS.exe
./nssm.exe set NestJSService Description "NestJSアプリケーション"
./nssm.exe set NestJSService AppNoConsole 1
./nssm.exe set NestJSService AppRestartDelay 1000
./nssm.exe start NestJSService
Service "NestJSService" installed successfully!
Set parameter "Description" for service "NestJSService".
Set parameter "AppNoConsole" for service "NestJSService".
Set parameter "AppRestartDelay" for service "NestJSService".
NestJSService: START: この操作を正しく終了しました。

サービスから削除する場合はこう。

./nssm.exe stop NestJSService
./nssm.exe remove NestJSService confirm
NestJSService: STOP: この操作を正しく終了しました。
Service "NestJSService" removed successfully!

終わりに

「製品の NestJS のコードを見られないように隠蔽したい」という要望から調査を始めましたが、
かなり特殊な手順になってしましました。nexe のメンテナンスも現在は停滞しているようで、いつまでこの手順が使えるのかは分かりません。(Electronはどうやってるんだろう)

素直にexeファイルへのコンパイルがサポートされている言語で開発した方がよかったと思います。

追記 (2024/01/05)

公式でexe化がサポートされました。まだ実験段階っぽいですが、可能ならこちらを利用した方が良いと思います。
Single executable applications

14
10
0

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
14
10