はじめに
Deno Advent Calendar 2020 19日目の記事です🦕
この1年でDenoには沢山の変更や改善が行われました。
この記事では、2020年にDenoに加わった変更点をまとめます。
要約
- deno@v1がメジャーリリースされた
- denoの本体と
deno_std
が独立してバージョン管理されるようになった --unstable
オプションが導入されたdeno doc
コマンドが実装された- リンター(
deno lint
コマンド)が実装された - バンドラ(
deno bundle
コマンド)が大幅に改善された - テストランナー(
deno test
コマンド)が強化された - 型チェックがスキップできるようになった(
--no-check
) - ファイルウォッチャー(
--watch
)が実装された - アプリケーションをシングルバイナリ形式へパッケージングできるようになった(
deno compile
コマンド) - Language Serverが組み込まれた(
deno lsp
コマンド) - Web標準との互換性が向上した
std/wasi
モジュールが追加された
deno@v1がメジャーリリースされた
2020/05/13にdenoのv1がメジャーリリースされました🥳
初回のコミットからおよそ2年後の出来事のようです。
このメジャーリリースに合わせて、公式のブログポストが投稿されたり、Denoパーカー(※現在は売り切れ中です🥺)が発売されるなど、様々なことがありました。
denoの本体とdeno_std
が独立してバージョン管理されるようになった
denoには標準モジュールとしてdeno_stdが存在します。
元々、このdeno_std
とdenoの本体(CLI)はバージョンを一致させる方針で管理されていました。(例: deno@v0.40.0
に対応するdeno_std
のバージョンはv0.40.0)
しかし、deno v1.0.0のメジャーリリースの直前にこの方針が変更され、CLIとdeno_std
は独立したバージョンを持つように変更されました。(例: deno@v1.6.1
に対応するdeno_std
のバージョンは0.81.0)
なぜdeno_std
のバージョン管理方式が変更されたの?
これはdeno_std
の安定性などが理由です。
denoのCLIとは異なり、deno_stdはまだ安定版がリリースされていません。
いつdeno_std
の安定版がリリースされるの?
現在、Deno Standard Library Working Groupというdeno_stdを安定化させるための取り組みが開始されています。(詳しくは @kt3kさんの「Deno Standard Library Working Group について」の記事を参照ください)
そのため、推測ではありますが、2021年にはdeno_std
の安定版がリリースされると思います。
--unstable
オプションが導入された
Denoのメジャーリリース以降、「安定した機能」と「不安定な機能」を分離するために、--unstable
オプションが導入されました。
Denoにおいて不安定な機能を使用する際は、--unstable
オプションを指定する必要があります。
例えば、次のように不安定な機能(Deno.hostname()
)を使用したコードがあったとします。
console.log(Deno.hostname());
このファイルを実行する際は、--unstable
オプションを付与する必要があります。
# --unstableがないとエラー!!
$ deno run --allow-env sample.ts
error: TS2339 [ERROR]: Property 'hostname' does not exist on type 'typeof Deno'. 'Deno.hostname' is an unstable API. Did you forget to
run with the '--unstable' flag?
console.log(Deno.hostname());
# --unstableをつけるとうまくいく
$ deno run --unstable --allow-env sample.ts
不安定なAPIの一覧についてはこちらから参照できます。
deno doc
コマンドが実装された
Deno@v0.38.0にてdeno doc
コマンドが実装されました。
これにより、ソースコードの内容からAPIドキュメントを出力できるようになりました。
また、このコマンドの実装にともない、公式のドキュメンテーションサイトも作成されました。
使い方
リモートモジュールのAPIドキュメントを出力
試しにdeno_std
のTOMLモジュールのドキュメントを出力してみます。以下のように実行すると、関数やメソッドのシグネチャ及びJSDocの内容を元に、APIドキュメントが生成されます。
$ deno doc https://deno.land/std@0.81.0/encoding/toml.ts
Defined in https://deno.land/std@0.81.0/encoding/toml.ts:732:0
function parse(tomlString: string): Record<string, unknown>
Parse parses TOML string into an object.
@param tomlString
Defined in https://deno.land/std@0.81.0/encoding/toml.ts:724:0
function stringify(srcObj: Record<string, unknown>): string
Stringify dumps source object into TOML string and returns it.
@param srcObj
ローカルモジュールのAPIドキュメントを出力
ローカルファイルのドキュメントを出力したいときは、そのファイルへのパスを指定します。また、引数としてクラス名または関数名を指定すると、それに関するドキュメントのみを出力することもできます。
# mod.tsからconnect関数のドキュメントを出力
$ deno doc ./mod.ts connect
Defined in file:///home/uki00a/ghq/github.com/uki00a/redis/redis.ts:2098:0
async function connect(options: RedisConnectOptions): Promise<Redis>
Connect to Redis server
@param options
@example
const conn = connect({hostname: "127.0.0.1", port: 6379}) // -> TCP, 127.0.0.1:6379
const conn = connect({hostname: "redis.proxy", port: 443, tls: true}) // -> TLS, redis.proxy:443
ビルトインAPIのドキュメントを出力
ビルトインAPIのドキュメントを出力したいときは、--builtin
オプションを付与します。
$ deno doc --builtin Deno.version
Defined in lib.deno.d.ts:2058:2
const version: { deno: string; v8: string; typescript: string; }
Version related information.
APIドキュメントをJSON形式で出力
--json
オプションを指定すると、JSON形式で出力されます。
$ deno doc --json io.ts
[
{
"kind": "typeAlias",
"name": "Status",
"location": {
"filename": "file:///home/uki00a/ghq/github.com/uki00a/redis/
io.ts",
"line": 7,
"col": 0
},
"jsDoc": null,
"typeAliasDef": {
"tsType": {
"repr": "string",
"kind": "keyword",
"keyword": "string"
},
"typeParams": []
}
},
... 省略 ...
]
リンター(deno lint
コマンド)が実装された
Deno@v1.1.0にてdeno lint
コマンドが実装されました
これにより、deno単独でソースコードのlintができるようになりました。
また、このdeno lint
コマンドはRustで実装されており、とても速いのが特徴です。
$ deno lint --unstable chrome.ts
(no-inferrable-types) inferrable types are not allowed
let result: string = "";
^^^^^^^^^^^^^^^^^^^
at /home/uki00a/ghq/github.com/uki00a/carol/chrome.ts:520:18
hint: Remove the type, it is easily inferrable
(no-inferrable-types) inferrable types are not allowed
let error: string = "";
^^^^^^^^^^^^^^^^^^
at /home/uki00a/ghq/github.com/uki00a/carol/chrome.ts:521:18
hint: Remove the type, it is easily inferrable
Found 2 problems
Checked 1 file
deno lintコマンド
の詳細については、「Deno の組み込みリンター "deno_lint" の紹介 〜 ESLintの代替としても」の記事がよくまとまっていておすすめです。興味があればぜひご覧ください
バンドラ(deno bundle
コマンド)が大幅に改善された
Denoはバンドラ(deno bundle
コマンド)を組み込んでいます。
このバンドラがv1.5において、大幅に強化されました。
- ツリーシェイキングに対応
- バンドラが
tsc
からswc_bundler
(Rust製)に変更された(その結果、型チェックをスキップすれば、v1.4以前と比較してパフォーマンスが15倍にまで向上したようです) - dynamic importに対応
その他にも、denopackのようなサードパーティのバンドラやAleph.jsやDext.tsのようなSSR/SSGフレームワークも登場し、Denoにおけるフロントエンド周りのエコシステムも徐々に充実しつつある印象を受けます。
テストランナー(deno test
コマンド)が強化された
Denoはテストランナー(deno test
コマンド)を組み込んでいます。
このテストランナーにも様々な変更や改善が実施されました。
簡単な使い方
deno test
コマンドの使い方について、簡単に説明します。
まず、次のようなテストファイルを用意します。
import { assertEquals } from "https://deno.land/std@0.81.0/testing/asserts.ts";
function add(a: number, b: number): number {
return a + b;
}
Deno.test("add", () => {
assertEquals(add(1, 2), 3);
});
そして、コマンドラインから以下のコマンドを実行すると、テストが実行されます。
$ deno test
running 1 tests
test add ... ok (3ms)
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out (3ms)
主な変更点
カバレッジレポートのサポート
Deno@v1.4.0からカバレッジレポートの出力がサポートされました。
$ deno test -A --coverage --unstable
Check file:///home/uki00a/ghq/github.com/uki00a/carol/$deno$test.ts
running 9 tests
test Application#evaluate ... ok (92ms)
test Application#exposeFunction ... ok (106ms)
test Application#onExit ... ok (80ms)
test Application#serveFolder ... ok (200ms)
test Application#serveFolder with prefix ... ok (213ms)
test custom executablePath ... ok (4ms)
test Chrome#evaluate ... ok (118ms)
test Chrome#load ... ok (110ms)
test Chrome#bind ... ok (97ms)
test result: ok. 9 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out (1021ms)
cover file:///home/uki00a/ghq/github.com/uki00a/carol/deps.ts ... 100.000% (11/11)
cover file:///home/uki00a/ghq/github.com/uki00a/carol/test_util.ts ... 78.261% (54/69)
29 | assert(err instanceof Deno.errors.ConnectionReset);
30 | }
31 | }
32 | },
-----|-----
49 | assert(err instanceof Deno.errors.ConnectionReset);
50 | }
51 | }
52 | },
53 | });
54 | }
-----|-----
64 | assert(err instanceof Deno.errors.ConnectionReset);
65 | }
66 | },
67 | });
68 | }
... 省略 ...
cover file:///home/uki00a/ghq/github.com/uki00a/carol/logger.ts ... 81.250% (13/16)
10 | return console;
11 | }
12 | else {
詳細についてはDeno v1.4.0で実装された新機能の紹介の記事を参照ください。
リソースリークを検知するようになった
例えば、次のようにリソースの開放が適切に行われていないコードがあったとします。
async function doSomething(): Promise<void> {
const _file = await Deno.open("mod.ts"); // _fileがクローズされていない!!!
}
Deno.test("...", async () => {
await doSomething();
});
このテストを実行すると、次のようなエラーが発生します。
test ... ... FAILED (4ms)
failures:
...
AssertionError: Test case is leaking resources.
Before: {
"0": "stdin",
"1": "stdout",
"2": "stderr"
}
After: {
"0": "stdin",
"1": "stdout",
"2": "stderr",
"3": "fsFile"
}
Make sure to close all open resource handles returned from Deno APIs before
finishing test case.
at assert (deno:cli/rt/06_util.js:33:13)
at Object.resourceSanitizer [as fn] (deno:cli/rt/40_testing.js:81:7)
at async TestRunner.[Symbol.asyncIterator] (deno:cli/rt/40_testing.js:245:13)
at async Object.runTests (deno:cli/rt/40_testing.js:322:22)
at async file:///home/uki00a/ghq/github.com/uki00a/sample/$deno$test.ts:3:1
failures:
...
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out (4ms)
このようなエラーが発生した際は、リソースの開放漏れがないか確認してみましょう。
テストケースのフィルタリングがサポートされた(--filter
オプション)
--filter
オプションによって、実行するテストケースを絞りこめるようになりました。
# 名前に「hoge」と含まれるテストのみを実行
$ deno test -A --filter hoge
# 正規表現を使用した例: 名前が「auth」から始まるテストのみを実行
$ deno test -A --filter "/^auth.+$/" ./test.ts
型チェックがスキップできるようになった(--no-check
)
Deno@v1.2.0にて--no-check
オプションがサポートされました。
これにより、TypeScriptの型チェックをスキップする手段が提供されます。
# 型チェックをスキップしてスクリプトを実行
$ deno run --no-check script.ts
# 型チェックをスキップしてテストを実行
$ deno test --no-check test.ts
ファイルウォッチャー(--watch
)が実装された
Deno@v1.4.0からファイルウォッチャーが実装されました。
これにより、ファイルが変更された際にスクリプトを自動で再実行できるようになります。
$ deno run --watch --unstable cli.ts
ファイルウォッチャーの詳細については「Deno の組み込み機能、ソースコードの変更を検知してオートリロードする "File Watcher" の紹介」の記事を参照ください
アプリケーションをシングルバイナリ形式へパッケージングできるようになった(deno compile
コマンド)
Deno@v1.6.0にて、deno compile
コマンドが実装されました。
これにより、Denoで書かれたアプリケーションをシングルバイナリ形式へパッケージングできるようになりました。(ただし、まだ不安定な機能(--unstable
)という位置づけです)
$ deno compile --unstable https://deno.land/std@0.80.0/examples/welcome.ts
Check https://deno.land/std@0.80.0/examples/welcome.ts
Bundle https://deno.land/std@0.80.0/examples/welcome.ts
Compile https://deno.land/std@0.80.0/examples/welcome.ts
Emit welcome
$ ./welcome
Welcome to Deno 🦕
deno compile
コマンドの詳細については「Deno 1.6.0 がリリースされたので主要機能の紹介」の記事にて詳しく解説されていますので、興味があればぜひご覧ください
Language Serverが組み込まれた(deno lsp
コマンド)
Deno@v1.6.0から、DenoにLanguage Serverが組み込まれました。
deno lsp
コマンドを使うと、Language Serverを起動できます。
vscodeやVim/Neovimとの連携方法については、こちらの記事を参照ください。
Web標準との互換性が向上した
この1年で様々なWeb APIがDenoに実装されました。
-
FileReader
(v1.3.0〜) -
WebSocket
(v1.4.0〜) - prompt API (v1.5.0〜)
等
これにより、Web標準との互換性がさらに向上しました。
std/wasi
モジュールが追加された
caspervonbさんにより、標準モジュールにWASIモジュール(std/wasi
)が実装されました。
WASIについては、以下の記事を参照ください。
まとめ
- この1年でDenoには沢山の新機能が実装されました
- メジャーリリース以降、Denoの安定性は着実に向上しつつあります
- 標準モジュール(
deno_std
)の安定化はこれから行われていきます
明日は@kt3kさんの「Denoのディレクトリ構造2020」です