generated at
deno入門2018
以下古い情報keroxp2019/3/20
hr
denoが盛り上がり始めたのを感じたのでまとめるkeroxp2018/12/28
denoでWebSocketを実装したときの知見に基づいています
インストール方法
とりあえずmacOSに直接入れるのが一番楽
Dockerとか使う必要ない
公式に書いてあるとおり、
bash
$ curl -L https://deno.land/x/install/install.py | python
で入る
${HOME}/.deno に色々と入れていくスタイル
PATH=${HOME}/.deno/bin:$PATH でパスを通しておく
これで deno コマンドが使えるようになる
基本
TypeScriptしか動かない
deno コマンドがパッケージ解決、コンパイル、実行全部やる
基本的にはtsだが、CommonJSと異なるのが、パッケージ解決にURLしか使えない(と謳っている)ところ
ts
import { test } from "https://unpkg.com/deno_testing@0.0.5/testing.ts"; import { log } from "./util.ts";
この場合 test はネットから落としてきて log は同階層のファイル
.ts を省略できず、 / index.ts を表さない
Node.js における設計ミスで色々書かれている
個人的には package.json は柔軟性が高くて結局便利だったと思うんですけどねkeroxp
Ry(Ryan Dahl)が中央集権リポジトリを邪悪と断じたところで、ネットにパッケージを上げる以上そういうことは必要になると思うけど
現在だってnodeのモジュールはnpm以外からも入れることできるし(yarnpkg.com)
開発
Goと同じで単一ファイル(本当に単一ファイル)から開発を始められる
設定ファイルとかはいらない。
が、 tsconfig.json は作っておいたほうがエディタの恩恵を得られる
tsconfig.json
{ "compilerOptions": { "target": "es2018", "baseUrl": ".", "paths": { "deno": ["./deno.d.ts"], "https://*": [ "../../.deno/deps/https/*" ], "http://*": [ "../../.deno/deps/http/*" ] } } }
deno --types > deno.d.ts でdenoの型定義を出力できる
denoがURLから落としてくるモジュールは、 ~/.deno/deps に置かれていく
なので↑みたいなtsconfigを書くとエディタが探してきてくれる
denoで一度コンパイルする必要はある
denoパッケージ
denoはURLしかモジュールとして読み込めないが、denoだけは特別に読み込める
ts
import {Conn} from "deno"
その他パッケージ
deno_std
もともとexampleだったらしいが最近stdに昇格した
実際は準標準という扱いっぽい
で入るライブラリがいくつか入っている
testing/testing.ts とか net/http.ts とかをよく使う
denoのコアにhttpは入らないっぽいので、このhttpモジュールを使わなくてもよい
それともこれがコアに昇格することあるのだろうか?
一応Ry本人が書いているようだけど
httpを使いたいときはこう
ts
import {serve} from "https://deno.land/x/net/http.ts"
テストの書き方
コアに testing モジュールがある
Goと同じで同階層に _test.ts ファイルを作って開発していくスタイル
スタイルであってルールではない。テストファイルは単体でdenoれる
some_test.ts
import {test, assert} from "https://deno.land/x/testing/testing.ts" test(async function testSomething() { assert(1 === (2-1)) })
実行すると結果が出る
log
deno test.ts Compiling /Users/keroxp/Development/deno-ws/test.ts running 1 tests test testSomething ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
HTTPサーバのたて方
deno_stdのnet/http.tsを使う
server.ts
import {serve} from "https://deno.land/x/net/http.ts" (async function main() { for await (const req of serve("0.0.0.0:8080")) { if (req.url === "/") { const contentType = req.headers.get("content-type"); await req.respond({ status: 200, headers: new Headers({ "Content-Type": contentType }), body: new TextEncoder().encode("Hello!") }) } } })();
bash
$ deno server.ts --allow-net
node.jsと比べると色々な示唆がある
1. nodeのhttpの server.on("request", (req, res) => {}) から、ES2018のAsync Iterator構文に変わっている
ここで serve はPromiseを返すジェネレータである
これがいいのかどうかはちょっとわからない
一つのコンテクストで複数のAsync Iteratorを反復するためには無名async関数を実行して開きっぱなしPromiseを作る必要がある??
2. res がない
req: ServerRequest オブジェクトでresponse返す
それ以外はNode.jsのreqと似ている感じ
3. 非同期処理はasyncのみ
コールバック、イベント駆動の処理はない
4. メソッドチェーンみたいなのもあんまりない
やることはメソッド一発でやれ的な意思を感じる
5. * default エクスポートをほとんど使っていない
export const/function を多用している
CommonJSからTSModuleへという意思を感じる
なんと require 使えないので!
6. ESの Iterable 機能を使いまくろうとしている
req.headers もオブジェクトではなく、 Headers クラスのインスタンス
Headersは一応ESの仕様だが、Iterableにするために変なmixin実装をしている
{}じゃないので req.headers["content-type"] みたいなのは使えない
これはちょっとどうなのかと思った。JSじゃないことを強めている気持ちを感じる
headersがSystem.Iteratorを実装しているのでこういう書き方ができる
ts
for (const [key, val] of req.headeres) { }
7. プロセスの権限が絞られている
--allow-net をつけて実行しないとネット関連の機能を使わせてくれない
fsへのアクセスもsandbox化されているらしい。デフォルトだとReadOnly