はじめに
現在Node.jsはさまざまな用途で多く使われている。しかし、Node.jsの製作者Ryan Dahl(ライアン・ダール)によるとNode.jsには10の反省点があると言う。そして、Ryan Dahlはそれらを改善した言語であるDenoを開発した。この記事ではDenoの紹介と導入を記述する。Denoのインストール方法などはMacOSでのみ動作確認した。他OSの場合で動かない場合は公式ドキュメントを参照していただきたい。
Deno
Denoは、V8を使用し、Rustで構築された、シンプルでモダンかつセキュアなJavaScriptおよびTypeScript用ランタイムです。
公式サイトより引用(DeepLより翻訳)
DenoはNodeでの開発経験を生かしたものとなっている。DenoはV8、Rust、Tokioに基づいたランタイムである。また、セキュリティと生産性に重きを置いており、大きく5つの特徴がある。
- 明示的に有効にしない限り、ファイル、ネットワーク、環境変数へのアクセスはできず、デフォルトでも安全
- TypeScriptをそのまま扱える
- 単一の実行形式ファイル
- 依存関係インスペクタ(deno info)やフォーマッター(deno fmt)などの便利な機能が組み込まれている
- Denoで動作保証されたレビュー済みの標準ライブラリーがある
Nodeの反省点
詳しくは説明しないが、以下の反省点を省みてDenoは作成された。
- 非同期処理にpromiseを使用しなかったこと(2009年に一時的に追加されたが)
- ビルドシステムにGYPを使用したこと
- node_modulesを採用したこと
- package.jsonを採用したこと
- 拡張子を除外したこと
- index.jsによる依存関係の解決を採用したこと
- V8のサンドボックス環境の破壊するような実装をしたこと
Nodeとの比較
- TypeScriptをデフォルトサポート
- npmを使用しない(node_modulesやpackage.jsonなどを使わない)
- 非同期処理にpromissを採用し、APIを再設計
- モジュールの扱いをES Module方式に統一
- ファイル、ネットワーク、環境変数へのアクセスに許可が必要
- ブラウザとの互換性向上
これらの変更によって、Nodeの反省点を改善や生産的で安全なスクリプト環境を達成できたが、Nodeで培われた多くの資産が使えなくなるという欠点もある。
Denoのインストール
インストールは好みのOSで好みの方法で行うと良い。ここでは公式に書かれている方法を紹介する。リリースページからのダウンドードも可能だ。
MacOS
- Shell
$ curl -fsSL https://deno.land/x/install/install.sh | sh
- Homebrew
$ brew install deno
Windows
- PowewShell
$ iwr https://deno.land/x/install/install.ps1 -useb | iex
- Chocolatey
$ choco install deno
- Scoop
scoop install deno
Linux
- Shell
$ curl -fsSL https://deno.land/x/install/install.sh | sh
インストールのテスト(バージョン確認)
インストールをテストするためにdeno --version
またはdeno -V
を実行し、バージョンが出力されることを確認する。
deno 1.14.1
アップデート
denoのバージョンはdeno upgrade
によって最新のバージョンに更新される。また、deno upgrade --version x.y.z
でバージョンx.y.zにアップデートされる。
対話型
deno
を実行すると対話型でDenoが使える。簡単な計算や構文の確認時などに便利。
Hello World
次にDenoを実際に動かしてみる。ここでは公式で紹介しているhttps://deno.land/std/examples/welcome.tsを実行してみる。ファイルの内容はアクセスすれば分かるが、console.log("Welcome to Deno 🦕")
だ。
deno run https://deno.land/std/examples/welcome.ts
で実行することができ、Welocome to Deno 🦕
と出力される。このように細かい設定などをしなくても息をするかのようにtsファイルを実行することができる。
パーミッション
Denoの特徴として「明示的に有効にしない限り、ファイル、ネットワーク、環境変数へのアクセスはできず、デフォルトでも安全」がある。ここではファイル、ネットワーク、環境変数などにアクセスする方法を紹介する。アクセスの許可はファイル実行時に与えることができる。
通常の実行はこのように行う。
deno run https://deno.land/std/examples/welcome.ts
全てのパーミッションを許可するときはこのように行う。
deno run --allow-all https://deno.land/std/examples/welcome.ts
このように--allow-hoge
のようにhogeに指定したもののアクセスを許可することができる(全て許可は-Aでも可)。
パーミッションリスト
-
--allow-all
または-A
で全て -
--allow-read={許可するファイル}
でファイルの読み込み、--allow-write{許可するファイル}
でファイルの書き込み(=以降無しで全てのファイル) -
--allow-net={許可するサイト}
でネットワークアクセス(=以降無しで全てのサイト) -
--allow-env
で環境アクセス -
--allow-plugin
でプラグインの読み込み -
--allow-run
でサブプロセスの実行 -
--allow-hrtime
で高性能の時間測定
実例
ネットワークアクセスを許可しなければサイトにアクセスできないことを確認後、許可することでアクセスできることを確認する。
準備のため以下のような適当なファイルを用意した。
const result = await fetch("https://deno.land/");
console.log(result);
これを通常通り実行すると以下のようなエラーが出る。
$ deno run fetch.ts
Check file:fetch.ts
error: Uncaught PermissionDenied: Requires net access to "deno.land", run again with the --allow-net flag
const result = await fetch("https://deno.land/");
^
at deno:core/01_core.js:106:46
at unwrapOpResult (deno:core/01_core.js:126:13)
at Object.opSync (deno:core/01_core.js:140:12)
at opFetch (deno:ext/fetch/26_fetch.js:65:17)
at mainFetch (deno:ext/fetch/26_fetch.js:220:61)
at deno:ext/fetch/26_fetch.js:443:11
at new Promise (<anonymous>)
at fetch (deno:ext/fetch/26_fetch.js:412:15)
at file:fetch.ts:1:22
次に、エラー文にも書かれているように--allow-net
をつけてネットワークアクセスを許可した状態で実行する。
$ deno run --allow-net fetch.ts
Response {
body: ReadableStream { locked: false },
bodyUsed: false,
headers: Headers {
"access-control-allow-origin": "*",
age: "5369",
"cache-control": "public, max-age=0, must-revalidate",
connection: "keep-alive",
"content-disposition": 'inline; filename="index"',
"content-type": "text/html; charset=utf-8",
date: "EEE, dd mmm yyyy HH:mm:ss GMT",
etag: 'W/"7d0c68ff2b382b4f36bd27cfd9c447a2df012a6e7183c896295567b4a4e6a102"',
server: "deploy/asia-northeast1-a",
"strict-transport-security": "max-age=63072000; includeSubDomains; preload",
"transfer-encoding": "chunked",
"x-vercel-cache": "HIT",
"x-vercel-id": "hnd1::9t84z-1633395860304-259194a942bb"
},
ok: true,
redirected: false,
status: 200,
statusText: "OK",
url: "https://deno.land/"
}
上記の結果から--allow-net
をつけることでアクセス可能であることが確認できた。もちろんfetch先のhttps://deno.land/だけを指定して--allow-net=deno.land
としても実行可能だ。
参考