ts-loader(webpack)を用いてのTypeScript開発の際、Node.js実行のためのshebangでTypeScriptのコンパイルエラーが起きたときの対応メモ
なんだかタイトルが長ったらしくなってしまった。
Node.js製のCLIツールを作っていた。 npmにてリリースして、globalインストールして使う予定だ。
そちらのツールに関する内容は本題ではないので、一旦そちらは脇にどけておく。
(たぶん、またどこかでそれについても書くと思う。ってか、このあと、話題に関係する形でコミット内容をしれっと貼らせていただきます。だけども、まだ開発段階です。)
そのようなツールを作る場合、Node.jsではファイルの先頭に shebang
を記述して、実行環境のnodeを参照するようにする必要がある。
#! /usr/bin/env node
今回このような形式のNode.jsのCLIツールをTypeScriptで書いていた。
ビルド環境はwebpack。ts-loader
を用いてビルドしている。
ところがこの shebang
を書いた状態でビルドすると、下記のようなエラーになってしまった。
Module parse failed: Unexpected character '#' (1:0)
shebang
が認識されていないようだ。
下記のStack overflowの回答を元に対応した。
解決方法
shebang-loader
をインストールする。
npm install --save shebang-loader
webpack側に設定する。
なお shebang-loader
自体はコンパイル時に shebang
を消しているだけで、コンパイル後のソースに持っていってくれたりはしない。
shebang-loader/index.js at master · JavascriptIsMagic/shebang-loader · GitHub
そのためwebpack側で直接 shebang
をコンパイル後のソースにも追加するという、割と泥臭い対応を行う必要がある。
( shebang-loader
側では仕組み的にそこまで行うことは出来なそう?)
実際に書き換えたDiffが下記となる。
iff --git a/webpack.config.js b/webpack.config.js index 3cbcad0..7978c19 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,3 +1,4 @@ +const webpack = require('webpack'); const isProduction = process.env.NODE_ENV === "production"; module.exports = { @@ -8,7 +9,7 @@ module.exports = { rules: [ { test: /\.ts$/, - use: ["ts-loader"], + use: ["ts-loader", "shebang-loader"], exclude: /node_modules/ } ] @@ -18,5 +19,8 @@ module.exports = { }, output: { filename: "index.js" - } + }, + plugins: [ + new webpack.BannerPlugin({ banner: "#!/usr/bin/env node", raw: true }), +] };
これでビルドエラーがなくなり、コンパイル後のソースにも shebang
が追加されたため、実行も問題なくできるようになった。
実際に対応した際のコミットはこちらになる。
(以前もこちらのブログに書いたかもしれないが、JUGEM XMLをMarkdownに変換するためのツールとなります。)