Denoは先日v1.25で2022/08/25にnpm対応したぞーと発表したのですが、そのバージョンではExperimental npm support
、あくまで実験的サポートであり、まだ実戦投入できる段階ではありませんでした。
そんなわけで実際に使えるのはまだまだ先だねえと思っていたのですが、2022/11/14に公開されたv1.28で早くもExperimental
が取れました。
はえーよ。
ということで以下は該当のリリースノートの紹介です。
Deno 1.28: Featuring 1.3 Million New Modules
Deno 1.28を公開できたことをうれしく思います。
本リリースでは、npmの互換性を安定させました。
すなわち、130万以上のnpmモジュールをDenoがインポートできるようになったことを意味します。
これによってPrisma・Mongoose・MySQLなどお気に入りの永続化モジュール、React・Vueなどのフロントエンドフレームワークを使用できるようになり、アプリの構築がこれまで以上に簡単安全に行えるようになります。
Denoを使えば、より簡単に、より安全にnpmを使用できます。
Denoのビルトインツールチェーン、ファーストクラスライブラリ、IDEサポートが、あなたの生産活動をより高速にします。
またDenoの安全側に倒したパーミッションモデルは、安全性の怪しいパッケージについて心配する必要を減らし、開発だけに集中できるよう支援します。
最新のJavaScriptはES ModulesとWeb標準APIで構築されるべきだとの持論をDenoは持っており、このリリースにおいてもその姿勢を変えることはありません。
npmモジュールのインポートは、標準に即した方法でURLを経由して行われます。
我々は、fetch・Request・ResponseといったWebAPIを用いて、何のブラウザを使っているかに影響されない未来へと向かっています。
Denoは、モダンで安全な環境であなたのお気に入りのnpmモジュールを使えるようにすることで、npmを一段上のステージへと引き上げました。
npmを使いこなすため、今週は毎日ハウツーガイドを公開する予定です。
TwitterやYoutubeをぜひフォローしてください。
Installing or Upgrading Deno
既にDenoがインストールされている場合は、1コマンドでアップグレードできます。
deno upgrade
初めてインストールする場合は、以下のコマンドを実行しましょう。
# MacOS and Linux
curl -fsSL https://deno.land/install.sh | sh
# Windows
irm https://deno.land/install.ps1 | iex
その他のインストール方法についてはこちらをご覧ください。
Using npm
npm:
という指定で、npmパッケージを使用することができます。
import { chalk } from "npm:chalk@5";
またImport Mapsでは、以下のように指定します。
{
"imports": {
"chalk": "npm:chalk@5"
}
}
npm scriptsやCLIもDenoから実行可能です。
deno run --allow-env --allow-read npm:create-vite-extra
サブコマンドが必要であれば、以下の形式で指定します。
deno run npm:<package_name> <subcommand>
例として、Denoでnpx prisma init
を実行するには以下のようにします。
deno run npm:prisma init
Security
npmはソフトウェアを簡単に共有・インストールできるようにしましたが、依存関係をインストール・実行する際に何の確認も行っていないため、サプライチェーン攻撃に非常に脆弱となっています。
typosquattingやソーシャルエンジニアリング、そしてその他の脆弱性を窓口に悪意のあるモジュールがアップロードされ、実運用されているNodeアプリケーションにインストールされ、多くのユーザの機密情報が危険に晒されることがあります。
Denoでは、依存関係のあるサードパーティライブラリがシステムにアクセスしようとした際に通知を行い、そしてアクセスを制限することができます。
deno run npm:install-malware
⚠️ ┌ Deno requests write access to /usr/bin/.
├ Requested by `install-malware`
├ Run again with --allow-write to bypass this prompt.
└ Allow? [y/n] (y = yes, allow; n = no, deny) >
より詳しく知りたい場合はpermissions systemを参照してください。
No package.json
Denoでのnpmの使用は、よりシンプルです。
npm install
は必要ありません。
初めて実行した際に自動的にインストールされます。
package.json
は必要ありません。
コードベースを複雑にするノイズを減らします。
node_modules
フォルダも必要ありません。
グローバルなディレクトリに一度だけキャッシュされます。
なお後方互換性のために--node-modules-dirを使うこともできます。
Denoで今すぐ生産性を上げましょう。
tester・formatter・linterなど多くのビルトインツールチェーンと、ネイティブのTypeScriptサポートによって、余計なインストールや設定作業に手を取られることなく、今すぐコードを書き始めることができます。
Ongoing Work
我々の目標は、できるかぎり多くのnpmモジュールをDenoで動かせるようにすることです。
package.jsonが作業ディレクトリに存在する前提で動作しているといった特殊なモジュールは、まだ互換していない可能性があります。
我々は今後数か月で、そのようなパッケージについても対応を行っていく予定です。
我々は現在、幾つかのNodeテストスイートを用いて、Denoでも動作することを確認しており、この範囲をさらに広げていく予定です。
また、コミュニティから報告されたエッジケースについても対応していきます。
deno compile
をはじめ一部のDenoサブコマンドは、まだnpmに対応していません。
この対応作業は#15960のチケットで進行しています。
より互換性を高めていくため、もしnpmモジュールで問題が発生したら是非Issueを上げてください。
多くの目さえあれば、ほぼ全ての非互換はなくせると我々は確信しています。
Auto discovery of the lock file
Denoはv1.0からロックファイルをサポートしていますが、これを使うためにはユーザが自己責任で--lock=<filename>
とフラグを指定する必要があり、不満の温床になっていました。
このような状況から、ロックファイルはほとんど使われないことになっていました。
Deno v1.28からは、設定ファイルdeno.json
が見つかった場合は自動でロックファイルを作成するようになりました。
ロックファイルは、設定ファイルと同じ場所にdeno.lock
という名前で配置されます。
さらに、新しい依存関係が見つかった際にはロックファイルも自動更新されます。
この自動検出シナリオのため、--lock-write
フラグの動作が拡張されました。
ロックファイルを更新するためにこのフラグを渡す必要はありません。
このフラグを渡すと、ロックファイルが強制的に作成されるようになります。
もしロックファイルの自動検出を無効にしたい場合は、--no-lock
フラグを使いましょう。
また--lock
フラグは引数を省略できるようになり、省略した場合のデフォルト値として./deno.lock
が使用されます。
Changes to Deno APIs
Stabilizations
本リリースでは、以下のAPIがstableとなりました。
今後--unstable
フラグを使う必要はありません。
・Deno.bench()
・Deno.gid()
・Deno.networkInterfaces()
・Deno.systemMemoryInfo()
・Deno.uid()
New unstable Deno.Command API
実験的実装だったDeno.spawn
・Deno.spawnSync
・Deno.spawnChild
が削除され、統一のAPIとしてDeno.Command
コマンドが追加されました。
基本的な非同期呼び出しはこうです。
let c = new Deno.Command("echo", { args: ["foo"] });
let { stdout, stderr } = await c.output();
基本的な同期呼び出しはこうです。
let c = new Deno.Command("echo", { args: ["foo"] });
let { stdout, stderr } = c.outputSync();
ストリーミングを含む、少し高度な非同期処理の例です。
const c = new Deno.Command("cat", { stdin: "piped" });
c.spawn();
// catの出力をファイルにパイプする
const file = await Deno.open("output.txt", { write: true });
await c.stdout.pipeTo(file.writable);
const stdin = c.stdin.getWriter();
await stdin.write(new TextEncoder().encode("foobar"));
await stdin.close();
const s = await c.status;
console.log(s);
V8 10.9
V8の最新リリース10.9にアップグレードされました。
これまでは10.8でした。
ほとんどは内部的な改良ですが、ユーザ向けのAPI変更も一部含まれています。
・Symbols as WeakMap keys
・unship array grouping (proposal)
全ての変更点についてはこちらを参照してください。
Manual rewrite
Denoの成長に合わせて、マニュアルも成長してきました。
そのため、あちらこちらに継ぎ足しがなされ、徐々に整理がつかなくなってきました。
このリリースでは、目次とテキストをリファクタリングし、シンプルでわかりやすいものにしました。
またnpmの使い方を解説するセクションも追加しました。
ドキュメントには、常に改善の余地があります。
改善点を見付けた場合は、ぜひプルリクエストを送ってください。
Launch Week
Denoとnpmで何が作れるようになったかを示すため、今週は毎日チュートリアルとハウツーガイドをYouTubeの動画で、また他の有用なリソースで紹介していきます。
Denoを商用利用していて、技術的質問がある場合は、Deno Office Hoursをご利用ください。
エンジニアが30分あなたのお手伝いをします。
TwitterやYoutubeをフォローして、最新情報を見逃さないようにしましょう。
感想
これまでDeno導入を躊躇する一因となっていたnpm非対応問題が、ここにおいてついに解決を見ました。
さらに、単にnpmが使えるようになって便利!ってだけではなく、きちんと安全装置まで組み込んであるのが素晴らしいですね。
この仕組みのおかげで、予め与えておいたパーミッション以上のことをやろうとしても動作しません。
まともだったライブラリに後からマルウェアが混入したなどの事故・事件の被害を軽減できるわけです。
もちろんパーミッションの範囲内での悪さはできるので完全に防げるというわけではないですし、何も考えずに--allow-allとか与えたら台無しなので、単にDenoを使っていれば安全というわけではありませんが、現状の何もしないnpmよりは遥かに良いことは間違いありません。
このパーミッションの仕組みはBunにも存在しないため、Bunに対する明白な利点として挙げられるでしょう。
この大きな改善により、これまでDenoを導入することが難しかった環境にも、容易に組み込むことができるようになったことでしょう。
さっそく試してみてはいかがでしょうか。