DenoのDemo
執筆の動機
Deno誕生から4年たち、MDN Web Docsの「ブラウザーの互換性」欄にDenoの情報が掲載されるようになっていたので、 そろそろDenoを触ってみようとおもいました。
Denoとは?
Node.jsの作者Ryan Dahlが、Node.jsで後悔している事を克服するために開発をはじめた、新しいJavaScript及びTypeScriptのランタイム環境です。
- セキュリティ強化
- ES Moduleだけ使う
- Typescriptビルドイン
- 単体の実行ファイルで動く
- モダンな開発環境で使う
- 可能な限りブラウザ互換にする
下記のアナグラムがプロジェクトをよく表していますね。。。
Developers Summit 2022のスライド にDeno Landの日野澤さんがポイントをまとめているので、 詳しくスライドを御覧ください🙇🏻
Deno ja Slack Community
Deno Example
サンプルコードはこちらをチェック
Deno install
とりあえず、公式に従ってDenoをinstallします。
$ deno --version
# 執筆時時点のバージョンは下記になります。
deno 1.22.0 (release, x86_64-apple-darwin)
v8 10.0.139.17
typescript 4.6.2
Visual Studio Codeの設定
Deno Official: Using Visual Studio Codeに従い、Visual Studio Codeの設定を行います。
拡張機能の追加
- vscode_deno 拡張機能を追加します。
- Denoプロジェクト用のワークスペースを作成する。
VSCodeのコマンドパレットから下記コマンドでsettingsファイルが作成されます。
> Deno: Initialize Workspace Configuration
settings.json
- VSCodeで保存時にformatterが動くように設定
-
deno.config
で設定ファイルを指定- この設定ファイルで組み込みTypeScriptコンパイラ・フォーマッタ、リンタをカスタマイズできる(後続で設定します)
{
"deno.enable": true,
"deno.lint": true,
"deno.unstable": true,
"deno.config": "./deno.jsonc",
"[typescript]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "denoland.vscode-deno"
}
}
つくるもの
今回はURLをわたすとQRコードを生成する簡単なアプリを作成していきます。
ディレクトリ構成
下記ディレクトリ構成でファイルを作成していきます。
.
├── README.md
├── deno.jsonc
├── lock.json
└── src
├── deps.ts
├── server.ts
└── validator
├── isUrl.ts
└── mod.ts
設定ファイル:deno.jsonc
- この設定ファイルで組み込みTypeScriptコンパイラ・フォーマッタ、リンタをカスタマイズできる。
-
JSON
とJSONC
がサポートされている。-
JSONC
はコメントが自由にかけるので、今回はJSONC
で記載します。
-
-
TypeScriptの設定
{
// TypeScriptの設定
"compilerOptions": {
"lib": ["deno.window"],
"strict": true
},
}
Linterの設定
{
// Linter設定
"lint": {
"files": {
"include": ["src"],
"exclude": ["public"]
},
"rules": {
"tags": ["recommended"],
"exclude": [
]
}
},
}
Formatterの設定
{
// Formatter設定
"fmt": {
"files": {
"include": ["src/"],
"exclude": [".vscode", ".env"]
},
"options": {
"useTabs": true,
"lineWidth": 100,
"indentWidth": 2,
"singleQuote": true,
"proseWrap": "preserve"
}
}
}
Code
今回は、Denoの基本的な機能を使っていきたいので、シンプルにDenoの標準ライブラリ(Standard Library)を使って、QRコードを生成して、HTMLを返します。
Denoでは、コアチームによって動作の保証されたStandard LibraryとThird Party Modulesがあります。どちらもDeno landから確認できます。
もうすこし複雑なアプリケーションをつくるなら、Oakなどのフレームワークを利用するのがいいでしょう。
まずは、/src/server.ts
を作成します。
import { log, qrcode, serve } from './deps.ts';
import { isUrl } from './validator/mod.ts';
async function handler(req: Request): Promise<Response> {
const url = new URL(req.url);
const targetUrl = url.searchParams.get('url') || '';
const qrCode = await qrcode(targetUrl);
if (!isUrl(targetUrl)) {
const body = JSON.stringify({ message: 'Not Found' });
return new Response(body, {
status: 404,
headers: {
'content-type': 'application/json; charset=utf-8',
},
});
}
return new Response(
`<html>
<head>
</head>
<body>
<h1>QR Code Generator</h1>
<img src="${qrCode}">
</body>
</html>`,
{
headers: {
'content-type': 'text/html; charset=utf-8',
},
});
}
const PORT = parseInt(Deno.env.get('PORT') ?? '8000');
log.info(`🦕 Starting server on port ${PORT}....`);
serve(handler, {
port: PORT,
});
deps.ts
Denoでは、deps.tsで外部モジュールimportをまとめて、depsから参照するのがお作法になっている。 依存関係をまとめることで、バージョン変更などdepsを変更するだけでよくなる。
Ryan Dahl氏がNode.jsで後悔していたpackage.jsonの解になる部分かなと(Node.jsでpackages.jsonを作ったことを後悔している)
// Standard library dependencies
export * as log from 'https://deno.land/std@0.140.0/log/mod.ts';
export { serve } from 'https://deno.land/std@0.140.0/http/server.ts';
// Third-party dependencies
export { qrcode } from 'https://deno.land/x/qrcode@v2.0.0/mod.ts';
Lockファイル
Node.jsでいうyarn.lock
package.lock.json
リモートのモジュールに依存すると、リモート側のファイルに変更があった場合に本番モジュールがローカルモジュールとは異なる依存関係のコードを実行される可能性があります。
下記コマンドでlockファイルを生成する
$ deno cache --lock=lock.json --lock-write ./src/deps.ts
リモートのモジュールの内容が変更されていると、lockファイルのhash値が変わるため、比較して整合性をチェックできる
下記コマンドで整合性チェックをしつつ、リモートモジュールのダウンロードができる
$ deno cache --reload --lock=lock.json src/deps.ts
Task runnerの設定
Nodeでいうscripts
をここで設定できる。
Denoにはビルドインコマンド が用意されているため、
nodeのようにわざわざrimraf
とかいれなくてもOSを気にしなくてよいので、いいですね。
{
...
// Taskの設定
"tasks": {
"dev": "deno run -A --watch ./src/server.ts"
}
}
Taskを実行
早速タスクを実行してみましょう。
$ deno task dev
今回は、queryParamのurlからQRコードを生成するので、http://localhost:8000/?url=https://www.google.com
でアクセスします。
するとQRコードが表示されます。
スマホからQRコードを読み取ると無事googleのページが開きます。
Deno Deploy
Deno Deployは、JavaScript、TypeScript、およびWebAssemblyを、世界中のエッジでユーザーの近くで実行できるようにする分散システムです。
supabaseやNetlifyでdeno deployが利用されているようです。
Netlify Edge Functions
Supabase Functions
今回はdeno deployを利用して、先程のQRコードGeneratorをデプロイしてみます。
コスト
そのうち料金がアナウンスされるみたいですが、2022/05/22時点では、無料で利用できるようです。 詳細はPrice & Limitをご確認ください。
Rate Limitをこえると、logにでるみたい。
2022/05/25追記
Deno Deploy Beta 4 がリリースされました。
Free PlanとProプランができるっぽい
The Free plan includes 100k requests/day, 10ms CPU time per request, and up to 100 GiB data transfer a month. The Free plan also includes GitHub integration, which allows you to deploy on push with both Private and Public repositories.
The Pro plan starts at $10/month, which includes up to 5 million requests/month, 50ms CPU time per request, wild card subdomains, and data transfer at $0.30/GiB. Requests over 5 million will cost $2/million requests.
Freeプランでは、
100kリクエスト/日、1リクエストあたりのCPU時間10ms、1ヶ月100GiBまでのデータ転送が可能です。
また、FreeプランにはGitHubインテグレーションが含まれており、PrivateとPublic両方のリポジトリを使ってPushでデプロイすることができます。
Proプランは月額10ドルからで、
最大500万リクエスト/月、1リクエストあたり50msのCPU時間、ワイルドカードサブドメイン、0.30ドル/GiBのデータ転送が含まれます。500万回を超えるリクエストは、2ドル/100万回のリクエストとなります。
Region
Tokyo (asia-northeast1)
Osaka (asia-northeast2)
Deployしてみる
- Deno Deployからgithubでログインする
- 右上の
New Project
から新しいプロジェクトを作成する
- 対象のレポジトリ・ブランチ・エンドポイントを指定するとプロジェクトが作成され、デプロイされます。
- 「View」ボタンから確認すると無事デプロイされれいることが確認できます。
めっちゃ簡単ですね 🎉
また、設定したブランチに変更をpushすると、自動的にデプロイが走ります。
反映もはやい🚄
フロントエンドでのDenoの可能性
DenoのフレームワークはFresh.js・Aleph.jsがあるみたいですが、
まだ、Productionでは利用できなさそうなので、今後の展開に期待したいですね。
最近ではRome ToolchainやBunといったtoolChainの統合が話題にあがっており、
フロント開発環境がどのようになっていくのか楽しみですね。
Denoでは、バンドラー・コンパイラー・フォーマッター・リンター・テスト・ベンチマークといった必ず必要になってくるツール群が組み込まれているのは、 良いなぁとおもいました。
Denoのフォーマッター・リンターはTypeScriptなら動くようなので、既存のプロジェクトのeslintを置き換えても動くようです。
今後は、eslint
からdeno lint
へ移行するということもあるのかなぁとおもいました。
まとめ
firebaseのcloud functionsなどは、デプロイに時間がかかりイライラした記憶がありますが、
deno deployは、ちょっと試したいときにサクッとつくれるので、いいなと思いました。
今後は、supabaseをつかってDB連携し、Denoでなにか作ってみたいですね。
(おぼえたてのGIPHY Captureを利用したくて動くGIF画像を多用してしまいました。)
Discussion