🙆‍♀️

NestJSをESModules化する

2024/08/07に公開

これはなに

モジュールシステムはCommonJSとESModulesがあり、NestJSをnest newで作成するとデフォルトでCommonJSになっています。

このことはtsconfig.jsonを見ても分かります。

tsconfig.json
{
  "compilerOptions": {
    "module": "commonjs",
    // ...
}

しかしここ数年でいろいろなライブラリがESModulesに対応する流れがあり、NestJSのプロジェクトでもESModules化をしてみます。

CommonJSで困ること

CommonJSのままだと、ESModules形式だけを提供するPure ESMのライブラリを読み込むことができません。

例えば、ログに色をつけるchalkv5.0.0以降はPure ESMとなっています

これをインストールして、適当な箇所に書いてみます。

src/app.service.ts
import { Injectable } from '@nestjs/common';
import chalk from 'chalk';

@Injectable()
export class AppService {
  getHello(): string {
    // chalkを使ってみる
    console.log(chalk.blue('Hello World!'));
    return 'Hello World!';
  }
}

これでNestを起動するとエラーになります。

npm run start        

> my-esm-2@0.0.1 start
> nest start

/Users/*****/dist/app.service.js:315
undefined
             ^

Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/*****/node_modules/chalk/source/index.js from /Users/*****/dist/app.service.js not supported.
Instead change the require of index.js in /Users/*****/dist/app.service.js to a dynamic import() which is available in all CommonJS modules.
    at TracingChannel.traceSync (node:diagnostics_channel:315:14)
    at Object.<anonymous> (/Users/*****/dist/app.service.js:11:17) {
  code: 'ERR_REQUIRE_ESM'
}

NestをESModules化することでこれを解消できます。

NestJSのESModules化

tsconfigを以下のように変更する。

tsconfig.json
{
  "compilerOptions": {
-   "module": "commonjs",
+   "module": "Node16",
+   "moduleResolution": "Node16",
    // ...
}

package.jsonに以下を追記する。

package.json
{
  // ...
+ "type": "module",
  // ...

import文の末尾に.jsをつける。

- import { AppService } from './app.service';
+ import { AppService } from './app.service.js';

これで無事にNestを起動して、chalkによって色付きのログが表示されるようになります。

Discussion