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はまだまだ試験段階なので本スライドの内容は変わるかもしれません。その点はご了承ください。

5cf7e9533a457726cd51232e06c1da9a?s=128

Masashi Hirano

February 01, 2019
Tweet

Transcript

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

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

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

    Deno for Users 3
  4. Design Mistakes in Node 4

  5. Design Mistakes in Node Node.js のオリジナル開発者Ryan Dahl 氏(ry) がJSConf EU

    2018 で発表したプレゼンテーション Node.js の設計ミスについて 現時点のNode.js を半年触ってみたがry が目指していたもの ではなかった Node.js の設計ミスを改善したDeno を開発していると発表 5
  6. https://youtu.be/M3BM9TB-8yA 6

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

  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
  9. 1. Not sticking with Promises 2009 年6 月にPromise を入れたが、2010 年2

    月には削除し た。それは間違いだった。 callback の方がパフォーマンスが優れていた async/await の抽象化のためにPromise は必要だった 9
  10. 1. Not sticking with Promises http://b.hatena.ne.jp/entry/365474721/comment/jovi0608 10

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

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

    12
  13. 3. The Build System (GYP) GYP(Generate Your Project) Chrome やV8

    やWebRTC にも使われていたが現在はGN に移 行している Node.js はそのままGYP を使っている 当時のChrome のビルドに乗っかった GN に比べてGYP は遅い Python2 系が必要 13
  14. 4. package.json package.json のmain のファイルをエントリポイントにして しまった npm リポジトリが中央集権になってしまった package.json のdependencies

    は ディレクトリをモジュールとして扱ってしまった 14
  15. 例えば以下のような構成になっていて . ├── foo │├── bar.js │└── package.json └── index.js

    foo/bar.js module.exports = () => { console.log("I'm bar.js"); } 15
  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
  17. 5. node_modules モジュール解決をとても複雜なものにしてしまっている ブラウザのセマンティクスからも外れてしまっている 17

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

  19. 6. require("module") without the extension ".js" ブラウザではJavaScript を読み込むときはファイルパスの拡 張子.js を省略しない

    複数のロケーションのファイルシステムを探索しなければ ならない 19
  20. 例えば、foo というモジュールをimport しようとすると、 import foo from './foo'; 20

  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
  22. https://teppeis.hatenablog.com/entry/2017/08/es-modules-in-nodejs 22

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

  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
  25. これまで話したNode.js の設計ミスを改 善したプロジェクトをry が始めた 25

  26. https://deno.land/ 26

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

  28. TypeScript 静的型付け可能なJavaScript のスーパーセット Deno ではユーザーがトランスパイルする必要なし TS ファイルを直接実行できる e.g. deno sample.ts

    実行時にDeno がビルドする Deno が持つAPI の型定義はDeno がサポート deno --types > deno.d.ts で出力 28
  29. ES Modules によるモジュール解決 CJS(require) ではなくESM(import) を使ったモジュールロー ディング ディレクトリではなくファイルを指定 package.json 不要

    URL で外部モジュールを読み込むことが可能 一度読み込むとキャッシュする --reload オプションを付けると再取得する 29
  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
  31. Secure な実行環境 デフォルトではネットワークアクセスなど安全ではない処 理は行えない 実行時にオプションを付けることで許可する --allow-net ネットワークアクセスを許可 --allow-write ファイル書き込みを許可 --allow-env

    環境変数参照を許可 --allow-run サブプロセスの起動を許可 -A すべて許可 31
  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
  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
  34. Node.js からの改善点 Node.js Deno Promise Callback ベース Promise ベース Security

    ネットワークアクセスや ファイル書き込みに制限 がない デフォルトでは不可能 Build System GYP GN Module package.json 、 node_modules に依存 URL によるリソース取得、ディ レクトリではなくファイルを 指定 34
  35. Deno Core 35

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

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

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

  39. Deno API の処理順 1. TypeScript がV8 上で実行される 2. FlatBuffers を用いてPrivileged

    な領域にデータを渡す 3. Rust でTokio を用いて非同期タスク登録 4. Rust でファイル操作などPrivileged な処理を行う 5. 処理したデータをFlatBuffers を用いてUnprivileged な領域 に返却 39
  40. https://tinyclouds.org/deno_20190124.pdf 40

  41. V8 Google が開発しているJavaScript エンジン Chrome やNode.js にも使われている V8 はTypeScript をそのまま実行できないのでDeno

    内部でJS に変換している 一度変換されたJS ファイルは~/.deno/gen にキャッシュさ れる コードを変更しない限りキャッシュを使って実行する 41
  42. https://tinyclouds.org/deno_20190124.pdf 42

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

    な領域からPrivileged な領域にデー タを渡すために使っている 43
  44. https://tinyclouds.org/deno_20190124.pdf 44

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

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

  47. Rust Mozilla が開発しているプログラミング言語 C 、C++ に代わるプログラミング言語を目指している Cargo というパッケージマネージャ兼ビルドツールがある Deno では様々なRust

    のパッケージ(Crate) を使っている tokio-fs: File System 操作 reqwest: HTTP クライアント etc... 47
  48. A Guide to Deno Core コアコントリビューターによるDeno のコアの内部の構成やAPI の実装 方法などの解説書 https://denolib.gitbook.io/guide

    48
  49. Let's Contribute! 49

  50. Deno for Users 50

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

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

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

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

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

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

    はまだ試作段階だからNode.js 使いましょう!by ry 57
  58. その他参考 deno について知っていること2019 年1 月編 - keroxp の Scrapbox (@keroxp)

    Deno を読む(1) - unde ned (@bokuweb) 58
  59. Thanks. 59