BLOGサブスレッドの日常
2020.05.10
Denoがついに1.0になるので、特徴をまとめた
s.kono
Deno 1.0 will be released immediately!
Deno 1.0に関する記事を見ました。
JavaScript/TypeScriptが好きな僕は、Denoを作るということが発表された時「すごい面白いものがくる!」と思いました。僕の中で、Node.jsはよく出来たツールだったので、それと同じようなものが生まれようとするとは思っていなかったのです。
面白いと思ったのは僕だけではなく、当時たくさんの人がそう感じたはずです(このissueからもそう感じました)。
あれから二年弱、ついにDeno 1.0がリリースされるということで、深夜についその記事を読みふけってしまいました…。
本記事では、Deno 1.0に関する記事に書かれていたことと、denoのドキュメントを眺めて集めた情報をまとめます。
超訳も一部取り入れようと思ったんですが、記事のコメントを見ると、記事自体の翻訳を許可していなさそうなので、自分なりの表現でまとめました。
Denoとは
JavaScript/TypeScriptの実行環境です。JavaScriptやTypeScriptが書かれたテキストファイルを読み込ませると、そのテキストファイル内のプログラムを実行してくれます。
つまりJavaScriptの実行環境であるNode.jsとの競合ということになります。
面白いのは、Node.jsもDenoも、作者は同じRyan Dahl (ry)さんだということです。
ryさんはNode.jsを作ってメンテナから外れた後、後悔したことがたくさんあったようです。Denoは、その後悔に基づき、ryさんが新たに作成したプロダクトです。
Denoがどうして生まれたかは、下記の記事をお読みください。すごく面白いです。
特徴
セキュリティ
- Denoはサンドボックス内で実行される
- サンドボックス内では、ファイルシステムやネットワークへのアクセス、サブプロセスの作成などができない
- ファイルシステムやネットワークへのアクセス、サブプロセスの作成などを行うにはパーミッションの指定が必要
- パーミッションの指定を行わず、例えばファイルシステムへのアクセスを行うAPIを実行した場合、
PermissionDenied
例外が発生する
- パーミッションの指定を行わず、例えばファイルシステムへのアクセスを行うAPIを実行した場合、
- パーミッションの指定は、Denoを使ってプログラムを実行する時の引数で行う
- 例えば、ファイルの読取りを許可する場合は
deno run --allow-read my-script.ts
のようなコマンドを発行する deno run -A my-script.ts
のように-A
オプションを加えると、全てのパーミッションを許可した状態でプログラムを実行できる- しかし、プログラムに必要以上のパーミッションを与えるのは推奨されない
deno --allow-read=/etc my-script.ts
のように、権限を適切に指定することが推奨されている- この場合
/etc
内のプログラムの読取のみ許可させることができる
- この場合
- 例えば、ファイルの読取りを許可する場合は
- コマンドでの実行時、パーミッションの指定を毎回行うのは面倒。解決する方法は、下記が挙げられる
- bash scriptを作る
- Drakeなどのタスクランナーを使用する
- Denoプログラムをインストールする
標準ライブラリ
- Denoの標準ライブラリstdは、Go言語の標準ライブラリを基にAPIが用意されている
- node.jsとの比較として、Available modules and their npm equivalentsを見ると分かりやすい
ビルドインツール
- Denoには標準でいくつかのツールが付属している
- テストランナー(
deno test
) - コードフォーマッタ(
deno fmt
) - バンドラー(
deno bundle
)- webpackのように複数のJavaScript/TypeScriptプログラムを一つにまとめるツール
- デバッガー
- ドキュメントジェネレータ(
deno doc
) - モジュール依存関係を見るツール(
deno info
) - lintツール(
deno lint
)- この機能は、執筆時点ではまだ作成中となっています
- テストランナー(
tsconfig.json
- DenoはJavaScriptだけでなく、TypeScriptプログラムの実行も可能であるため、
tsconfig.json
の指定が可能 - プログラム実行時に
-c
オプションをつけることで、任意のtsconfig.json
を指定することが可能deno run -c tsconfig.json my-script.ts
- サポートされているパラメータと、Denoでのデフォルト値はCustom TypeScript Compiler Optionsを参考のこと
Web互換API
- Denoにはfetch APIが標準で実装されている
- Node.jsでは標準で実装されておらず、Node Fetchが必要だった
- fetch API以外にも、DenoにはたくさんのWeb互換APIが用意されている
- 全てのWeb互換APIは、doc.deno.landから確認できる
- Denoで動かすプログラムは、ブラウザでもDenoでも動くようにすべき
Deno
名前空間下にあるメソッドを使用しないほうが良い
import
時の拡張子
- Denoでモジュールを読み込ませる時はファイル拡張子が必須
- 例)
import { MyClass } from './my-script.ts'
- 例)
- しかし、
import
文に拡張子を書くと、IDEに文法エラーがあると怒られてしまう- この問題は、今はVSCode拡張を導入し、Deno向けのプロジェクト内で有効化することで解決できる
パッケージマネージャ
- Denoには中央パッケージマネージャがない
- つまりNode.jsで言うところの
npm
がない - Denoで、サードパーティ製のプログラムを呼び出すには、
import
文に書くファイル名をURLにするだけでよい- もうNode.jsの 魔法の モジュール解決アルゴリズムはない
- つまりNode.jsで言うところの
- Denoでは、モジュール解決アルゴリズムとして
package.json
は使わない- 言い換えると、
package.json
内のdepedencies
やdevDependencies
といった辞書値は使用せず、モジュールの依存関係を解決する
- 言い換えると、
- Denoでは、モジュールのバージョン管理のために、
deps.ts
という特別なファイルを作成しておき、その中で使用するクラスのインポートを行うのが良いとされている - ダウンロードされたモジュールは、デフォルトでDenoを実行したカレントディレクトリではない、見えない場所にキャッシュされ、利用される
- ダウンロードされたモジュールのキャッシュを読み直す場合は、
--reload
オプションをコマンドに付与すれば良い - 見える場所にダウンロードされたモジュールのキャッシュを置く場合は、
$DENO_DIR
環境変数を指定する
- ダウンロードされたモジュールのキャッシュを読み直す場合は、
サードパーティ製ライブラリの使用
- DenoとNode.jsは原則APIの互換がないため、Node.js APIを使用しているサードパーティ製ライブラリはNode.jsモジュールをDenoで使用することは出来ない
- 例外として、一部互換のあるAPIがある
- Nodeとの互換性のあるAPI一覧
- Deno互換のサードパーティ製モジュールは、Third Party Modulesから検索可能
ファイルの監視
- Denoでのファイル監視(nodeで言うところのwatch)は、Rustのnotifyライブラリを使って実現されている
- ファイルの監視はいくつかの方法がある
- Deno.watchFs()APIを使う
- Denonを使う方法
- Denonはnodeでいうところのnodemonと同じ役割のもの
Denoを試してみる (on macOS)
記事の目的とは少し離れますが、試しにDenoを使ってみた時のコマンドとコード例です。
##
で始まっている行はコメントです。
DenoのインストールとHello, World!
## HomebrewでDenoのインストール
brew install deno
## Hello, World!
deno run https://deno.land/std/examples/welcome.ts
パーミッション
## ヘルプを表示
## ヘルプの中に、パーミッションのサンプルが書かれている
deno run -h
## パーミッションなしでファイルサーバープログラム起動
## PermissionDeniedでクラッシュすればOK
deno run https://deno.land/std/http/file_server.ts
## パーミッションありでファイルサーバープログラム起動
## 起動し、ブラウザからアクセスできればOK
deno run --allow-read --allow-net https://deno.land/std/http/file_server.ts
fetch API
- 下記をgithub-api.tsとして保存
async function fetchFromGitHub(path: string) {
const result = await fetch(`https://api.github.com${path}`)
return await result.json()
}
console.log('Fetching from / ...')
console.log(await fetchFromGitHub('/'))
console.log('')
console.log('Fetching from /users/octocat ...')
console.log(await fetchFromGitHub('/users/octocat'))
- コマンドラインで実行する
deno --allow-net ./github-api.ts
ドキュメントジェネレータの使用
- 下記をgithub-api.tsとして保存
/**
* Fetch Data from GitHub
*
* @param path URL Path
*/
export async function fetchFromGitHub(path: string) {
const result = await fetch(`https://api.github.com${path}`)
return await result.json()
}
console.log('Fetching from / ...')
console.log(await fetchFromGitHub('/'))
console.log('')
console.log('Fetching from /users/octocat ...')
console.log(await fetchFromGitHub('/users/octocat'))
- コマンドラインで実行する
deno doc ./github-api.ts
まとめ
Denoの特徴やNode.jsとの違いを見てきました。
見ていて考えされられたのは、DenoはNode.jsと比べると、思ったよりも多くの違いがあることについてです。
Node.jsとのAPIの違いも多く、多くのライブラリはDeno向けに書き直し、もしくはDenoとの互換性を保つためにリファクタリングが必要になります。そのため、すぐにDenoに移行することは出来ません。
1.0になったとはいえ、サードパーティ製ライブラリは少なく、Deno自体にもまだ十分な量のAPIはまだ用意されていません。
Web技術者にDenoの良さが認められ次第、徐々にコミュニティが大きくなり、サードパーティ製ライブラリも準備され、Node.jsからDenoへゆっくりと移り変わっていくもののように思いました。
実際のプロダクトにDeno組み込まれて使われるまでにはまだ時間がかかりそうです。仕事で使用するのはまだ先だと思います。
しかしTypeScriptを組み込むなど、Denoは現在のモダンな流れともマッチしたランタイムです。
Web技術者を勢いづけるには十分な設計の良さを持っているように感じました。
僕は気持ち的には、すぐにでも使い始めたいくらいです…!
参考元URL
おまけ
Denoのロゴって何なのか
Denoのロゴの絵はDino in the rainと呼ばれているっぽい?です。つまりロゴの中に書かれているのは、ヘビでもチンアナゴでもなく、首長竜類か恐竜の竜脚類ですね。
で、ここでdoc.deno.landのAPIを見てみると。
deno doc Loading中画像の恐竜めっちゃかわいいhttps://t.co/dvuAX5KWUt pic.twitter.com/yR5XL97Qi2
— ネスケ@むおおおお (@esperia09) May 9, 2020
足があって歩いてますね。ということで竜脚類の何かでした。
ちなみにうちにはこんなストラップがありまして。
かなり近くないですか。Denoって名前つけるしかない。
この記事を書いた人
s.kono