LoginSignup
6
5

More than 3 years have passed since last update.

denoを触ってみる

Last updated at Posted at 2020-05-16

denoはnodejsに代わる次世代javascript/typescriptランタイムです。
つい最近v1.0.0がリリースされたので触ってみたのですが、めちゃくちゃいい感じだったので感想をまとめます。

denoってそもそも何?というのは
https://qiita.com/so99ynoodles/items/c3ba2a528052827e3b3c
などがわかりやすいです。

(なお、サラッと触ってみただけなので間違いがある可能性があります。)

インストール

mac使いなので

brew install deno

で入りました。
直接installする場合は

curl -fsSL https://deno.land/x/install/install.sh | sh

で良さそうです。

チュートリアル

https://deno.land/manual/getting_started/first_steps
公式ドキュメントが死ぬほど読みやすい・・・

HelloWorld

最初のスクリプトは以下のURLに置いてありました。
当然のように拡張子は.tsです。

$ curl https://deno.land/std/examples/welcome.ts
console.log("Welcome to Deno 🦕");

実行してみます

$ deno run https://deno.land/std/examples/welcome.ts
Welcome to Deno 🦕

web上のtypescriptがそのまま実行されている・・・すごい!

httpリクエスト

denoはnodejsよりブラウザ互換なAPIを提供しているようです。
fetch() が使えます。

https//deno.land/std/examples/curl.ts
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
const url_ = Deno.args[0];
const res = await fetch(url_);

// TODO(ry) Re-enable streaming in this example.
// Originally we did: await Deno.copy(res.body, Deno.stdout);
// But maybe more JS-y would be: res.pipeTo(Deno.stdout);

const body = new Uint8Array(await res.arrayBuffer());
await Deno.stdout.write(body);

地味にトップレベルでawaitが使われていて感動。

これはさっきと同じコマンドでは実行できません。denoは明示的に権限を与えないとネットワークアクセスができないからです。
image.png

エラーメッセージも明瞭ですね。 --allow-net を付けて再実行します

image.png

ちなみに初回実行時は Download https://deno.land/std/examples/curl.ts などが標準エラー出力に出てくるようです。
2回目以降の実行ではキャッシュされているので出てきません。

また --allow-net オプションはドメインを指定しないと任意のドメインを許可するようです。

ファイル読み込み

https//deno.land/std/examples/cat.ts
for (let i = 0; i < Deno.args.length; i++) {
  let filename = Deno.args[i];
  let file = await Deno.open(filename);
  await Deno.copy(file, Deno.stdout);
  file.close();
}

image.png
(大事な部分はカット)
IOも明示的な許可が必要です。 --allow-read でディレクトリ単位に制限した読み込み許可を与えます。

TCPサーバ

https//deno.land/std/examples/echo_server.ts
const listener = Deno.listen({ port: 8080 });
console.log("listening on 0.0.0.0:8080");
for await (const conn of listener) {
  Deno.copy(conn, conn);
}

for awaitは非同期反復子をイテレートするjavascriptの構文ですね。(普段あまり使う機会ないので急に出てきてビックリした)

deno run --allow-net https://deno.land/std/examples/echo_server.ts ネットワークへのフルアクセスを付けて実行できます。

CLI

deno コマンドは リリース を見るとシングルバイナリ(!)のCLIとして提供されています。
deno run 以外のサブコマンドをいくつか触ってみます

repl

deno repl でREPLが起動します。サブコマンド無指定の deno でも同じです。
image.png

repl内では import はできないっぽい?

bundle

deno bundleはimportを辿って依存スクリプトを全てシングルファイルにバンドルしてくれます。
lodashはpureなjavascriptだからdenoで実行できると聞いたので、これを使って試してみました

hello.ts
import isString from "https://raw.githubusercontent.com/lodash/lodash/master/isString.js";
console.log(isString("abc")); // true

$ deno run hello.ts # denoでは実行可能
true
$ node run hello.ts # 当然nodeでは実行できない(importできないから)
internal/modules/cjs/loader.js:1023
  throw err;
  ^

Error: Cannot find module '/Users/moajo/deno/run'
...()

$ deno bundle hello.ts > bundle.js # bundle.jsにバンドル結果を吐く
Bundling "file:///Users/moajo/deno/hello.ts"
$ node bundle.js # nodeでも実行可能に!
true

install

denoで書いたスクリプトを呼び出すshell scriptを~/.deno/bin以下に置いてくれるコマンドです
せっかくなので依存があっても大丈夫かも検証します(例によってlodash)

lt10.ts
// 引数は10より小さいときにtrue,そうじゃないときにfalseを返すコマンド
import lt from "https://raw.githubusercontent.com/lodash/lodash/master/lt.js";
console.log(lt(parseInt(Deno.args[0]), 10));

特に役に立たないコマンドですがinstallしてみます。

$ deno install lt10 lt10.ts
Compile file:///Users/moajo/deno/lt10.ts
Download https://raw.githubusercontent.com/lodash/lodash/master/lt.js
✅ Successfully installed lt10
/Users/moajo/.deno/bin/lt10
$ lt10 9       
true
$ lt10 10
false

ちなみにdeno install したときにPATHが通ってないとちゃんと指摘してくれます。優しい。

ℹ️  Add /Users/moajo/.deno/bin to PATH
    export PATH="/Users/moajo/.deno/bin:$PATH"

実行可能ファイルの中身はこんな感じでした

$ cat `which lt10`
#!/bin/sh
# generated by deno install
deno "run" "file:///Users/moajo/deno/lt10.ts" "$@"

シンプルですね

typescriptサポート

denoは標準でtypescriptをサポートしているので、特に理由がなければ基本的にtypescriptを使ったほうが良さそうです。
一方で、型定義のないjavascriptコードを参照するためのサポートもちゃんと用意されています

compiler-hintをコメントで付けることで型定義を読み込んでくれます。型定義も当然URLで指定できるようです。

// @deno-types="./foo.d.ts"
import * as foo from "./foo.js";

tsconfigはデフォルトでstrictなオプションが指定されるようですが、-cオプションで指定することもできます。

deno run -c tsconfig.json mod.ts

個人的にはX-TypeScript-Typesカスタムヘッダーで型定義を指定できる機能がめちゃくちゃかっこよくて好きです。そのうちこれに対応したホスティングサービスも出てくるんでしょうか?

最後に

さらっと触ってみただけですが、UXが最高すぎて完全に惚れました。流行ってくれ!
ドキュメンテーションもわかりやすいですし、機能的にもめちゃくちゃ使いやすいです。
仕様上npmパッケージとの互換性がないのが唯一にして最大のつらみポイントですが、今後の発展に期待です。

リンク

日本のユーザコミュニティのscrapbox?
slackもある

参考

6
5
1

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
  3. You can use dark theme
What you can do with signing up
6
5