とりあえず ↓ を読む。
ふんわり理解だけど今んとこ 「 typescript で外部依存少なめな小さい部品を作りたい 」 なら使えそう。
- node.js 作者による v8 engine & rust base な js / ts runtime
- type check, lint, test, fmt など標準で全部入り + URL からスクリプトを実行とかもできる
- I/O とかもサポートしてて、独自組み込み API は Runtime APIs あたりにある
- Reading a file
- 権限周りは明示的に与える必要ある - 必要な権限だけを与えよう
- 要は「実行コマンド見たら io やってるとかわかる」ってのがいいらしい
- 開発環境や例とかでは
-A
で全許可したりしてる
- なんか各 platform 向けにバイナリ compile もできちゃう凄すぎ
- deno => npm への package 移植も可能っぽい
- denoland/dnt - github.com
- Deno を使って Node でも Deno でも動くライブラリを作る
- しかも Dual Package でだせるぽい
- スタイルガイド読んどくと、想定する使われ方や他人のコードわかりやすい
- express とか npm package 使わない前提の deno 製 web framework とかもあるぽい
CLI Command 一覧は Built-In Tooling あたり
# install
$ brew install deno
$ deno --version
> deno 1.33.2 (release, x86_64-apple-darwin)
> v8 11.4.183.1
> typescript 5.0.3
# upgrade example
$ chmod 711 $(where deno) # https://github.com/denoland/deno/issues/14829
$ deno upgrade --version 1.0.1
# zsh setting (completions)
$ mkdir ~/.zsh
$ deno completions zsh > ~/.zsh/_deno
$ exec $SHELL -l
# test `deno run`
$ deno run https://deno.land/std/examples/welcome.ts
# repl
$ deno repl
# type check, lint, fmt, bench, test
$ deno check main.ts
$ deno lint main.ts
$ deno fmt main.ts
$ deno bench main.ts
$ deno test
# hot reload with --watch flag
# https://deno.com/manual@v1.33.2/getting_started/command_line_interface#watch-mode
$ deno test --watch
$ deno run --watch main.ts
Starting a new project
Configuration File
TypeScript Configration
denoland/deno#15300 (comment)
denoland/deno#17099
- init で
deno.json
設定ファイルとmain.ts
main_test.ts
などの hello world script が生成される- tsconfig, lint, test, scripts (task), dependencies (imports) など全部入りなので適当に調整していく
- 初回の依存 download (deno run か deno cache --reload) で
deno.lock
生成される- 以降は
--lock
lock-write
flag の使い分けで依存管理する感じ
- 以降は
- npm 依存がっつり or deno 全振りかを決めてから setup していくのがよさそう
- npm 依存多いなら package.json compatibility 管理に倒しちゃってもいいかも
- そうでないなら下手に node っぽくせずちゃんと deno 標準にのっかるのがよさそう
Deno: Initialize Workspace Configuration
で .vscode/settings.json
生成。
- vscode-deno は default で on にならない
- あと deno の lint, fmt はカスタム前提じゃない
- ので deno 標準機能使うならある程度 settings.json をこねる感じになる
... ってことで、deno project では .gitignore
から .vscode/settings.json
外しておいたほうが良さそう。
!.vscode/settings.json
ts 同様に language server は以下コマンドで restart できる。
Deno: Restart Language Server
こんな。
$ deno test --watch
// main.test.ts
import { assertEquals } from "https://deno.land/std@0.186.0/testing/asserts.ts"
import { isNumber } from "./src/is-number.ts"
import { error2json } from "./src/error2json.ts"
Deno.test('is-number', async test => {
await test.step('string literal be fail', () => {
assertEquals(isNumber('1'), false)
})
await test.step('number literal be true', () => {
assertEquals(isNumber(1), true)
})
})
Formatter
How can I deno fmt on file save? #328
VSCodeで保存時に deno fmt するには
deno lint
は rule custom できない、多分やるつもりない- 代替としては eslint など別途使う or
deno fmt
で file save ごとに直す - single quote 強制や semi colon 抜きくらいならできた
vscode-deno で formatOnSave で deno.json
の fmt
rule を読むという感じ。
// .vscode/settings.json
{
"deno.enable": true,
"deno.lint": true,
"editor.formatOnSave": true,
"editor.defaultFormatter": "denoland.vscode-deno"
}
// deno.json
{
"fmt": {
"options": {
"singleQuote": true,
"semiColons": false
}
}
}
これで auto import とか時点では from "hoge";
とかになってるやつをファイル保存で from 'hoge'
とかに整形できる。
Basics > Modules
Import Maps
package.json compatibility
Integrity Checking & Lock Files
- deno は コードベースに依存先の cdn/package 名を書いとく という方式をとっている
- 基本
import/export
(esm) 方式で.ts
など拡張子を省略するなとのこと
- 基本
- で、初回実行時に local pc の global な cache 空間に DL され以降はそこから読まれる
- node の
node_modules
(local) にドカンと DL する方式とは全く異なる - 依存は URL, ファイルパスで行い、コード上の import を mapping するという考え
- 再ロードしたいときは
deno cache --reload
を使えとのこと
- node の
- cdn はざっくり ↓ から選ぶ、どっぷり deno 使うわけじゃなければ npm 互換がよさそう
- npm: - npm 互換
- deno.land - deno 公式 cdn
- esm.sh - npm のやつ esm 化して host してるとこ
- skypack.dev ↑ とほぼ同じかな?
- version 固定については
deno.lock
かvendor
のいずれかの戦略から選ぶ感じ- まず前提として、初回実行時に cache されて以降は cdn 側の「中身」が変わらない限り大丈夫
- ので ci で
deno cache --reload
(+deno.lock
生成) してdeno run --lock=deno.lock
でよき- 更新時には
deno cache --reload --lock=deno.lock --lock-write
かな?
- 更新時には
- 本番に出す前に
deno vendor
で全依存を download & git 管理する- Vendoring Dependencies
- 多分
deno vendor mod.ts
してdeno run --no-remote --import-map=vendor/import_map.json mod.ts
するイメージ - 多分 ci で cdn 落ちてたら困るケースならこっち
ちゃんと読んでないけど、npm package をガッツリつかった開発はまだ production ready じゃなさそう。
- deno 公式 lib 集で多分 go の standard library のまねっこ
- io, fs, path, testing など便利系が揃ってる
- まだ beta & deno 本体と独立した version 管理なので、指定 ver に気をつける
import { posix } from "https://deno.land/std/path/mod.ts"
posix.join("dist", "index.html");
// => unix なら dist/index.html に、win なら dist\index.html になるとか
- これは
npm i
とは別物 (後述する Modules の考え方がまるで違う) - 実行可能な deno script (.ts) を global に DL してくるというもの
- ざっくり deno 製の CLI ツールを落としてくる みたいな認識でいい
- git repo から web hook を使って tag ごとに publish みたいなことするらしい
- 勝手に api reference を組んでくれるので、それだけでも便利
denoland/dnt - github.com
Deno を使って Node でも Deno でも動くライブラリを作る
dntでDeno-firstなデュアルモジュールを作る
- dual package (cjs / mjs) 対応な npm library の開発環境 & publish が高速でできる
- cjs は top level await 使えないとか一部制限あり
- deno module を作って dnt で node 用コードを build し publish する流れ
- ignore してる
.npm
に build してそいつを publish する感じ
- ignore してる
- typescript の type declare (型宣言) も作ってくれるしゅごい
こんな感じかな。
// main.ts
export * from './a-func.ts'
export * from './b-func.ts'
import { build, emptyDir } from 'https://deno.land/x/dnt@0.35.0/mod.ts'
await emptyDir('./npm')
await build({
entryPoints: ['./main.ts'],
outDir: './npm',
shims: { deno: true },
package: {
name: '@', // TODO
version: Deno.args[0].replace(/^v/, ''),
description: '', // TODO
publishConfig: { access: 'public' }, // if scoped package
},
postBuild() {
Deno.copyFileSync('LICENSE', 'npm/LICENSE')
Deno.copyFileSync('README.md', 'npm/README.md')
},
})
{
"tasks": {
"dev": "deno test --watch",
"build": "deno run -A build.ts",
"link": "(cd npm && npm link)",
"publish:dry": "(cd npm && npm publish --dry-run)",
"publish:run": "(cd npm && npm publish)"
},
"test": {
"exclude": ["npm/"]
},
"lint": {
"exclude": ["npm/"]
},
"fmt": {
"exclude": ["npm/"]
}
}
// .vscode/settings.json
{
"deno.enable": true,
"deno.lint": true,
"deno.enablePaths": [
"./",
"!./npm/"
],
"editor.formatOnSave": true,
"editor.defaultFormatter": "denoland.vscode-deno"
}