🎃

Next.js + TypeScript + デコレータ + reflect-metadata を動かす

2021/04/27に公開

特殊な状況で恐縮ですが、Next.jsでデコレータを使おうとしてもうまく動いてくれません。
Next.jsでは、TypeScriptを設定なしで使えますし、TypeScript(tsc)はデコレータに対応していますが、Next.js + TypeScript + デコレータという組み合わせでは動いてくれません。

Next.js + デコレータを動かす

Next.jsでは内部ではBabelを使ってJSやTSをトランスパイルしています。したがってTypeScript(tsc)がデコレータに対応していても、Babelが対応していないとうまく動かないわけです。

したがいまして、以下のようなBabelの設定が必要です。

.babelrc.json
{
  "presets": [
    "next/babel"
  ],
  "plugins": [
    ["@babel/plugin-proposal-decorators", { "legacy": true }],
    ["@babel/plugin-proposal-class-properties", {"loose": true}]
  ]
}

@babel/plugin-proposal-decorators がデコレータに対応するためのものです。 @babel/plugin-proposal-class-properties はクラスにプロパティを生やせるようにするためのものです。自分のプロジェクトではclass property decoratorに対応するために必要でした。

Next.js + reflect-metadataを動かす

babel-plugin-transform-typescript-metadataを使って、reflect-metadataで使うメタデータ情報をコード上に埋め込むようにします。

.babelrc.json
{
  "presets": [
    "next/babel"
  ],
  "plugins": [
    ["babel-plugin-transform-typescript-metadata"]
    ["@babel/plugin-proposal-decorators", { "legacy": true }],
    ["@babel/plugin-proposal-class-properties", {"loose": true}]
  ]
}

なお、主要なブラウザー(IE除く)はReflectに対応しているようなので、reflect-metadataをimportする必要はないのですが、SSR部分ではNode.jsがReflectに対応していないため、importが必要です。注意してください。

以上、Next.jsでDIなどする際に必要なものをまとめました。
よろしくお願いします。

Discussion