$30 off During Our Annual Pro Sale. View Details »

Design Mistakes in Node & Deno #kng5 / deno

Design Mistakes in Node & Deno #kng5 / deno

関西Node学園 5時限目( https://nodejs.connpass.com/event/113631/ )でNode.jsの設計ミスについてとDenoの話をしました。
Denoはまだまだ試験段階なので本スライドの内容は変わるかもしれません。その点はご了承ください。

Masashi Hirano

February 01, 2019
Tweet

More Decks by Masashi Hirano

Other Decks in Programming

Transcript

  1. Deno
    A new way to JavaScript
    平野昌士@shisama
    https://deno.land/

    View Slide

  2. https://github.com/shisama/shisama

    View Slide

  3. Agenda
    Design Mistakes in Node
    Introduction to Deno
    Deno Core
    Deno for Users
    3

    View Slide

  4. Design Mistakes in Node
    4

    View Slide

  5. Design Mistakes in Node
    Node.js
    のオリジナル開発者Ryan Dahl
    氏(ry)
    がJSConf EU
    2018
    で発表したプレゼンテーション
    Node.js
    の設計ミスについて
    現時点のNode.js
    を半年触ってみたがry
    が目指していたもの
    ではなかった
    Node.js
    の設計ミスを改善したDeno
    を開発していると発表
    5

    View Slide

  6. https://youtu.be/M3BM9TB-8yA
    6

    View Slide

  7. 解説付き日本語訳
    https://yosuke-furukawa.hatenablog.com/entry/2018/06/07/080335
    7

    View Slide

  8. Design Mistakes in Node
    1. Not sticking with Promises.
    2. Security
    3. The Build System (GYP)
    4. package.json
    5. node_modules
    6. require("module") without the extension ".js"
    7. index.js
    8

    View Slide

  9. 1. Not sticking with Promises
    2009
    年6
    月にPromise
    を入れたが、2010
    年2
    月には削除し
    た。それは間違いだった。
    callback
    の方がパフォーマンスが優れていた
    async/await
    の抽象化のためにPromise
    は必要だった
    9

    View Slide

  10. 1. Not sticking with Promises
    http://b.hatena.ne.jp/entry/365474721/comment/jovi0608
    10

    View Slide

  11. 現在のNode.js
    では
    v8
    からutil.promisify
    が使える
    v10
    からfs.promises
    やdns.promises
    が使える(Experimental)
    https://nodejs.org/api/
    11

    View Slide

  12. 2. Security
    V8
    自体はとても優れたセキュリティsandbox
    になっている
    特定のアプリケーションでその点をもっと考慮できていれ
    ば、他の言語にはないセキュリティを担保できた
    例えば、lint
    を動かすだけなのにネットワークにアクセスす
    る必要はない
    12

    View Slide

  13. 3. The Build System (GYP)
    GYP(Generate Your Project)
    Chrome
    やV8
    やWebRTC
    にも使われていたが現在はGN
    に移
    行している
    Node.js
    はそのままGYP
    を使っている
    当時のChrome
    のビルドに乗っかった
    GN
    に比べてGYP
    は遅い
    Python2
    系が必要
    13

    View Slide

  14. 4. package.json
    package.json
    のmain
    のファイルをエントリポイントにして
    しまった
    npm
    リポジトリが中央集権になってしまった
    package.json
    のdependencies

    ディレクトリをモジュールとして扱ってしまった
    14

    View Slide

  15. 例えば以下のような構成になっていて
    .
    ├── foo
    │├── bar.js
    │└── package.json
    └── index.js
    foo/bar.js
    module.exports = () => {
    console.log("I'm bar.js");
    }
    15

    View Slide

  16. foo/package.json
    {
    "name": "foo",
    "version": "1.0.0",
    "main": "bar.js"
    }
    index.js
    const foo = require('foo');
    foo();
    // => I'm bar.js
    16

    View Slide

  17. 5. node_modules
    モジュール解決をとても複雜なものにしてしまっている
    ブラウザのセマンティクスからも外れてしまっている
    17

    View Slide

  18. https://tinyclouds.org/jsconf2018.pdf
    18

    View Slide

  19. 6. require("module") without the
    extension ".js"
    ブラウザではJavaScript
    を読み込むときはファイルパスの拡
    張子.js
    を省略しない
    複数のロケーションのファイルシステムを探索しなければ
    ならない
    19

    View Slide

  20. 例えば、foo
    というモジュールをimport
    しようとすると、
    import foo from './foo';
    20

    View Slide

  21. 見つかるまで以下の優先度で探索する
    1. ./foo
    2. ./foo.mjs
    3. ./foo.js
    4. ./foo.json
    5. ./foo.node
    6. ./foo/package.json // main
    で指定したファイルor
    ディレクトリ
    6-1. ./foo/bar
    6-2. ./foo/bar.mjs
    6-3. ./foo/bar.js
    6-4. ./foo/bar.json
    6-5. ./foo/bar.node
    6-6. ./foo/bar/package.json // main
    で指定したファイルor
    ディレクトリ
    6-6-1. ./foo/bar/hoge
    6-6-2. ./foo/bar/hoge.mjs
    ...
    7. ./foo/index
    8. ./foo/index.mjs
    ...
    21

    View Slide

  22. https://teppeis.hatenablog.com/entry/2017/08/es-modules-in-nodejs
    22

    View Slide

  23. 7. index.js
    index.html
    っぽく省略可能にしてしまった
    モジュールローディングを無駄に複雜にしてしまった
    require
    関数がpackage.json
    をサポートした後は特に不要に
    なった
    23

    View Slide

  24. 以下のようなディレクトリ構成の場合、
    ├── index.js
    └── modules
    ├── Bar
    │└── index.js
    └── Foo
    └── index.js
    index.js
    を指定しなくてもディレクトリを指定するだけでモジュール
    読み込みができてしまう
    // index.js
    を明示的に指定していない
    const bar = require("./modules/Bar");
    const foo = require("./modules/Foo");
    foo();
    bar();
    24

    View Slide

  25. これまで話したNode.js
    の設計ミスを改
    善したプロジェクトをry
    が始めた
    25

    View Slide

  26. https://deno.land/
    26

    View Slide

  27. Deno
    TypeScript
    をV8
    で実行するためのランタイム
    ES Modules
    によるモジュール解決
    Secure
    な実行環境
    27

    View Slide

  28. TypeScript
    静的型付け可能なJavaScript
    のスーパーセット
    Deno
    ではユーザーがトランスパイルする必要なし
    TS
    ファイルを直接実行できる e.g. deno sample.ts
    実行時にDeno
    がビルドする
    Deno
    が持つAPI
    の型定義はDeno
    がサポート
    deno --types > deno.d.ts
    で出力
    28

    View Slide

  29. ES Modules
    によるモジュール解決
    CJS(require)
    ではなくESM(import)
    を使ったモジュールロー
    ディング
    ディレクトリではなくファイルを指定
    package.json
    不要
    URL
    で外部モジュールを読み込むことが可能
    一度読み込むとキャッシュする
    --reload
    オプションを付けると再取得する
    29

    View Slide

  30. URL
    による外部モジュールを読み込むことが可能
    インターネット上のモジュールを指定
    import * as log from "https://deno.land/x/std/log/mod.ts";
    log.debug("Hello world");
    相対パスで指定
    import hello from "./hello.ts";
    hello();
    30

    View Slide

  31. Secure
    な実行環境
    デフォルトではネットワークアクセスなど安全ではない処
    理は行えない
    実行時にオプションを付けることで許可する
    --allow-net
    ネットワークアクセスを許可
    --allow-write
    ファイル書き込みを許可
    --allow-env
    環境変数参照を許可
    --allow-run
    サブプロセスの起動を許可
    -A
    すべて許可
    31

    View Slide

  32. ネットワークへのアクセス
    ネットワークにアクセスするためには --allow-net
    を付ける
    $ deno hello_http.ts --allow-net
    OK.
    --allow-net
    を付けないと実行時に許可を求めてくる
    $ deno hello_http.ts
    Deno requests network access to "listen". Grant? [yN]
    32

    View Slide

  33. 許可しなかった場合はパーミッションエラー
    Deno requests network access to "listen". Grant? [yN]N
    PermissionDenied: permission denied
    at DenoError (deno/js/errors.ts:19:5)
    at maybeError (deno/js/errors.ts:38:12)
    at maybeThrowError (deno/js/errors.ts:26:15)
    at sendSync (deno/js/dispatch.ts:67:5)
    at listen (deno/js/net.ts:145:19)
    at serve (file:///Users/admin/.deno/deps/https/deno.land/x/http/http.ts:53:20)
    at main (file:///Users/admin/hello_http.ts:6:23)
    at eval (file:///Users/admin/hello_http.ts:11:1)
    at _drainRunQueue (deno/js/compiler.ts:209:38)
    at run (deno/js/compiler.ts:587:10)
    33

    View Slide

  34. Node.js
    からの改善点
    Node.js Deno
    Promise Callback
    ベース Promise
    ベース
    Security
    ネットワークアクセスや
    ファイル書き込みに制限
    がない
    デフォルトでは不可能
    Build
    System
    GYP GN
    Module
    package.json

    node_modules
    に依存
    URL
    によるリソース取得、ディ
    レクトリではなくファイルを
    指定
    34

    View Slide

  35. Deno Core
    35

    View Slide

  36. https://tinyclouds.org/jsconf2018.pdf
    36

    View Slide

  37. Deno
    の構成
    レイヤー
    (
    言語)
    役割
    TypeScript
    ユーザーが使うAPI
    のインターフェース。File System

    Network
    へのアクセスなどはできない
    C++
    V8
    とのバインディング。TypeScript
    とRust
    のデータの受
    け渡し
    Rust
    File System
    やNetwork
    へのアクセスなどを行う
    Privileged
    なレイヤー
    37

    View Slide

  38. https://tinyclouds.org/deno_20190124.pdf
    38

    View Slide

  39. Deno API
    の処理順
    1. TypeScript
    がV8
    上で実行される
    2. FlatBuffers
    を用いてPrivileged
    な領域にデータを渡す
    3. Rust
    でTokio
    を用いて非同期タスク登録
    4. Rust
    でファイル操作などPrivileged
    な処理を行う
    5.
    処理したデータをFlatBuffers
    を用いてUnprivileged
    な領域
    に返却
    39

    View Slide

  40. https://tinyclouds.org/deno_20190124.pdf
    40

    View Slide

  41. V8
    Google
    が開発しているJavaScript
    エンジン
    Chrome
    やNode.js
    にも使われている
    V8
    はTypeScript
    をそのまま実行できないのでDeno
    内部でJS
    に変換している
    一度変換されたJS
    ファイルは~/.deno/gen
    にキャッシュさ
    れる
    コードを変更しない限りキャッシュを使って実行する
    41

    View Slide

  42. https://tinyclouds.org/deno_20190124.pdf
    42

    View Slide

  43. FlatBuffers
    Google
    が開発しているシリアライゼーションライブラリ
    ProtocolBuffers
    より速い
    パースなしでシリアライズされたデータにアクセス可能
    FlatBuffers
    専用のフォーマットでスキーマ定義を書く
    Deno
    ではUnprivileged
    な領域からPrivileged
    な領域にデー
    タを渡すために使っている
    43

    View Slide

  44. https://tinyclouds.org/deno_20190124.pdf
    44

    View Slide

  45. Tokio
    非同期処理を扱うRust
    のライブラリ
    イベント駆動型のNon-Blocking I/O
    マルチスレッドによる並列処理が可能
    45

    View Slide

  46. https://tinyclouds.org/deno_20190124.pdf
    46

    View Slide

  47. Rust
    Mozilla
    が開発しているプログラミング言語
    C
    、C++
    に代わるプログラミング言語を目指している
    Cargo
    というパッケージマネージャ兼ビルドツールがある
    Deno
    では様々なRust
    のパッケージ(Crate)
    を使っている
    tokio-fs: File System
    操作
    reqwest: HTTP
    クライアント
    etc...
    47

    View Slide

  48. A Guide to Deno Core
    コアコントリビューターによるDeno
    のコアの内部の構成やAPI
    の実装
    方法などの解説書
    https://denolib.gitbook.io/guide
    48

    View Slide

  49. Let's Contribute!
    49

    View Slide

  50. Deno for Users
    50

    View Slide

  51. 公式ページ - deno.land
    https://deno.land
    51

    View Slide

  52. Install
    Deno
    をインストール
    $ curl -L https://deno.land/x/install/install.sh | sh
    $ export PATH=$HOME/.deno/bin:$PATH
    インストール後の検証
    $ deno https://deno.land/thumb.ts
    Downloading https://deno.land/thumb.ts...
    Compiling https://deno.land/thumb.ts
    52

    View Slide

  53. deno_std
    https://github.com/denoland/deno_std
    コアとは別で公式が提供している標準モジュール
    HTTP
    、アサーション、Path
    などよく使われるモジュールは
    揃っている
    最近ではWebSocket
    とかPrettier
    が入った
    53

    View Slide

  54. Registry
    https://github.com/denoland/registry
    公式のパッケージレジストリ
    誰でも開発したモジュールを登録することができる
    PR
    を投げて承認されれば登録される
    登録されると https://deno.land/x/
    から始まるURL
    でモジュ
    ール参照可能になる
    54

    View Slide

  55. awesome-deno
    https://github.com/denolib/awesome-deno
    Deno
    のモジュールやツールや記事が紹介されている
    55

    View Slide

  56. フレームワークも既に作られている
    ※上記は一部です。他にもあります。
    56

    View Slide

  57. まとめ
    Node.js
    には設計ミスによる課題が残っている
    Deno
    はNode.js
    の課題を改善している
    Deno
    はシンプルで各レイヤーが疎結合な設計になっている
    ユーザーやライブラリが増えてきて盛り上がりを感じる
    Deno
    はまだ試作段階だからNode.js
    使いましょう!by ry
    57

    View Slide

  58. その他参考
    deno
    について知っていること2019
    年1
    月編 - keroxp

    Scrapbox (@keroxp)
    Deno
    を読む(1) - unde ned (@bokuweb)
    58

    View Slide

  59. Thanks.
    59

    View Slide