Denoにタスクランナーが搭載された件(`deno task`コマンド)


Deno1.20では、タスクランナーが本体に入りました。基本的にはnpm scriptsと同じなのですが、デフォルトでクロスプラットフォーム対応になっているなど、違う所もあります。

deno task コマンドの使い方

deno.json(c)でタスクの内容を設定します。
※deno.json(c)の構文についてはこちらの記事を参照してください。

deno.jsonc(例)
{
  "tasks": {
    // "<タスク名>": "<タスク内容>" の形で定義する
    // deno task hello
    "hello": "deno eval \"console.log('hello')\"",
    // deno task world
    "world": "deno eval \"console.log('world')\"",
    // deno task args hello world # output: ["hello", "world"]
    "args": "deno eval \"console.log(Deno.args)\"",
    "echo": "echo hello world",
    "nesting": "echo $(deno eval \"console.log('hello world')\")",
    "concat1": "echo 1 && echo 2",
    "concat2": "deno eval \"Deno.exit(1)\" || echo 2",
    "pipe": "echo hello world | deno eval \"Deno.stdin.readable.pipeTo(Deno.stdout.writable)\"",
    "var": "VAR=hello && echo $VAR && deno eval \"console.log(Deno.env.get('VAR'))\"",
    "export": "export VAR=hello && echo $VAR && deno eval \"console.log(Deno.env.get('VAR'))\""
  }
}

このdeno.jsonを置いたディレクトリより下層のディレクトリでは、定義したタスクが有効になります。
タスク名として使えるのは英数字+コロン(1文字目は必ず英字)です。(^[A-Za-z][A-Za-z0-9_\\-:]*$
以下、このdeno.jsonを使って解説していきます。

タスクを実行

ターミナルでdeno task <タスク名>というコマンドを打つと、タスクが実行されます。

> deno task hello
Warning deno task is unstable and may drastically change in the future
Task hello deno eval "console.log('hello')"
hello

タスク名の後に引数を渡すと、その引数はそのままコマンドに渡されます。

> deno task args hello world # hello worldが引数の部分
Warning deno task is unstable and may drastically change in the future
Task args deno eval "console.log(Deno.args)" "hello" "world"
[ "hello", "world" ]

タスクのリストを表示

ターミナルでdeno taskコマンド(引数無し)を打つと、タスクのリストが表示されます。

> deno task
Warning deno task is unstable and may drastically change in the future
Available tasks:
- args
    deno eval "console.log(Deno.args)"
- concat1
    echo 1 && echo 2
- concat2
    deno eval "Deno.exit(1)" || echo 2
- echo
    echo hello world
# ...(以下略)

タスクの文法

コマンドの連結や入れ子がサポートされています。

文法 意味
<command1> && <command2> command1が成功(exit code 0)したらcommand2を実行する
  • echo hello && echo world
<command1> || <command2> command1が失敗(exit code 1)したらcommand2を実行する
  • deno eval 'Deno.exit(1)' || echo hello
<command1> ; <command2> command1が終了したら成功・失敗に関係なくcommand2を実行する
  • echo hello ; echo world
<command1> & <command2> command1command2を並列に実行する
  • echo hello & echo world
<command1> | <command2> command1のstdout出力をcommand2にパイプする
  • echo hello world | deno eval 'Deno.stdin.readable.pipeTo(Deno.stdout.writable)'
<command1> |& <command2> command1のstdout出力とstderr出力をcommand2にパイプする
  • deno eval 'console.log(1); console.error(2);' |& deno eval 'Deno.stdin.readable.pipeTo(Deno.stdout.writable)'
VAR_NAME=<val> シェル変数VAR_NAMEに値を代入する(値は生成したプロセス内で利用できない)
  • VAR=hello && export $VAR
export VAR_NAME=<val> 環境変数VAR_NAMEに値を代入する(値は生成したプロセス内で利用できない)
  • export VAR=hello && deno eval \"console.log(Deno.env.get('VAR'))\"
$VAR_NAME シェル変数や環境変数を使用する
  • VAR=hello && export $VAR
$(<command>) コマンドを入れ子にする
  • echo $(deno eval 'console.log(1)')
! <command> コマンドの終了コードを無視し、必ず成功扱いにする
  • ! deno eval 'Deno.exit(1)'

現在は上記のような構文がサポートされています。将来的にはリダイレクト(command > file_name)やglob(./*.js)がサポートされる予定です。

クロスプラットフォーム対応

npm scriptsでは、WindowsとLinuxとMac OSの間でクロスプラットフォームなコマンドを書くためにはshxなどのパッケージをインストールする必要がありました
(例えばrmなどはwindowsに存在しないので、このパッケージを通して使う必要がある)

一方、deno taskではクロスプラットフォーム対応のコマンドが最初から組み込まれています
Deno1.20時点では以下のコマンドがデフォルトで組み込まれており、Windowsでも追加パッケージ無しで使えるようになっています。

  • cp : ファイルをコピーする
  • mv : ファイルを移動する
  • rm : ファイルを削除する(例:rm -rf [FILE]...
  • mkdir : ディレクトリを作成する(例:mkdir -p DIRECTORY...
  • pwd : カレントディレクトリを表示する
  • sleep : n秒待つ(例:sleep 1
  • echo : 文字列を表示する
  • exit : シェルからexitする

使い方については、同名のUnixコマンドと同じです。

これらのコマンドはdeno_task_shellリポジトリで実装されています。他に追加してほしいコマンドがあればこのリポジトリでissueを開くと追加してくれるそうです。
LinuxやMacでこの組み込みコマンドではなくOSのコマンドを使用したい場合は、shコマンドを使います(例:sh -c cp source destination

まとめ

  • deno.json(c)でタスクを使うとdeno taskコマンドから利用可能
  • デフォルトでクロスプラットフォーム対応している

従来は、Denoのタスクランナーとしてvelociraptorやmakefileが使われていました。一方で、Deno本体にクロスプラットフォームなタスクランナーを搭載してほしいという要望もあり、deno taskが実装されました。

最近では標準ライブラリにdotenvモジュールが追加されるなど、基本的に全員がインストールすることになるツールはデフォルトで使えるようになっているのがDenoの嬉しい所です。