search
LoginSignup
3

More than 1 year has passed since last update.

posted at

updated at

【2020年】Denoに加わった変更点のまとめ

はじめに

Deno Advent Calendar 2020 19日目の記事です🦕

この1年でDenoには沢山の変更や改善が行われました。
この記事では、2020年にDenoに加わった変更点をまとめます。

要約

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())を使用したコードがあったとします。

sample.ts
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の代替としても」の記事がよくまとまっていておすすめです。興味があればぜひご覧ください:exclamation:

バンドラ(deno bundleコマンド)が大幅に改善された

Denoはバンドラ(deno bundleコマンド)を組み込んでいます。

このバンドラがv1.5において、大幅に強化されました。

  • ツリーシェイキングに対応
  • バンドラがtscからswc_bundler(Rust製)に変更された(その結果、型チェックをスキップすれば、v1.4以前と比較してパフォーマンスが15倍にまで向上したようです)
  • dynamic importに対応

その他にも、denopackのようなサードパーティのバンドラやAleph.jsDext.tsのようなSSR/SSGフレームワークも登場し、Denoにおけるフロントエンド周りのエコシステムも徐々に充実しつつある印象を受けます。

テストランナー(deno testコマンド)が強化された

Denoはテストランナー(deno testコマンド)を組み込んでいます。
このテストランナーにも様々な変更や改善が実施されました。

簡単な使い方

deno testコマンドの使い方について、簡単に説明します。
まず、次のようなテストファイルを用意します。

test.ts
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" の紹介」の記事を参照ください:exclamation:

アプリケーションをシングルバイナリ形式へパッケージングできるようになった(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 がリリースされたので主要機能の紹介」の記事にて詳しく解説されていますので、興味があればぜひご覧ください:exclamation:

Language Serverが組み込まれた(deno lspコマンド)

Deno@v1.6.0から、DenoにLanguage Serverが組み込まれました。

deno lspコマンドを使うと、Language Serverを起動できます。

vscodeやVim/Neovimとの連携方法については、こちらの記事を参照ください。

Web標準との互換性が向上した

この1年で様々なWeb APIがDenoに実装されました。

これにより、Web標準との互換性がさらに向上しました。

std/wasiモジュールが追加された

caspervonbさんにより、標準モジュールにWASIモジュール(std/wasi)が実装されました。

WASIについては、以下の記事を参照ください。

まとめ

  • この1年でDenoには沢山の新機能が実装されました
  • メジャーリリース以降、Denoの安定性は着実に向上しつつあります
  • 標準モジュール(deno_std)の安定化はこれから行われていきます

明日は@kt3kさんの「Denoのディレクトリ構造2020」です:exclamation:

参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
3