虎の穴開発室ブログ

虎の穴ラボ株式会社所属のエンジニアが書く技術ブログです

MENU

Deno 1.4 1.5 1.6 へのアップデートと変更事項まとめ

この記事は、虎の穴ラボ Advent Calendar 2020の20個目の記事です。
昨日は、CloudDNSとCloudSQLによるデータベース負荷分散についてJUNE-JUNEさんが、明日はReactについてNSSさんの記事が投稿されます。ぜひこちらもご覧ください。

qiita.com

皆さんこんにちは、ラボのおっくんです。
ますます年末が近づいて来ました。

さて、去る 2020 年 9 月 14 日に Deno 1.4、10 月 28 日に Deno 1.5、12 月 9 日に Deno1.6 が続けてリリースされました。

今回は、以前公開した Deno 1.0 の導入から機能紹介に引き続き、Deno 1.4 と 1.5、1.6 の変更事項の中から気になったものを中心にアップデートの方法から紹介していきたいと思います。

toranoana-lab.hatenablog.com

実行環境

  • OS:macOS Catalina 10.15.5

アップデートのやり方

今回は Deno 1.1.0 から Deno 1.6.0 へのアップデートを行います。

アップデートする Deno 1.1.0 を導入した時のコマンドは以下の通りです。

$ curl -fsSL https://deno.land/x/install/install.sh | sh

アップデートは、以下のコマンドで実施しました。

$ deno upgrade
# バージョン指定する場合は次のコマンドで実行します。
# deno upgrade --version 1.5.0

ネットワーク環境もあるでしょうが、完了するまでに 5 分程度かかりました。

方法については、こちらに記載がありました。 Deno Manual

Deno 1.4

Deno 1.4 での変更事項をDeno 1.4 リリースノートを元に確認します。

deno.land

console.log の CSS スタイリング

Deno 1.4 から、console.logの出力に CSS のスタイリングが効くようなりました。

例えば、以下コードがあります。

> console.log("%coutput", "color:red")
output #<= 赤色の文字色で表示される

%cをつけることで、文字列へのスタイリングが効きます。 コメントでは赤色の文字色で表示される見込みと記しましたが、この機能については以下の注意があります。

Deno supports the CSS properties color, background-color, font-weight, font-style, text-decoration-color, and text-decoration-line. Support for these properties, and custom rgb, hex, and hsl colors depend on your terminal's support for ANSI.

雑な意訳ですが、「color, background-color, font-weight, font-style, text-decoration-color, text-decoration-line のプロパティと、カスタム rgb、hex、および hsl の色のサポートは、端末のサポート次第です。」

確かに、mac の標準コンソールでこちらを実行すると色の指定により濃淡の差異は確認できましたが、 設定した色自体は確認できませんでした。

font-weight:boldについては、有効に動作して太字で出力されるのを確認できました。

deno.land/std が変更されました

JSON 形式ファイル専用の読み書き関数が削除されています。

削除されたもの

  • writeJson
  • writeJsonSync
  • readJson
  • readJsonSync

例として、readJson を使ったときに 1.4 以降では以下のようにエラーになることを確認しました。

# 対話モードでdenoを起動
$ deno
> const data = await readJson("data.json");
Uncaught ReferenceError: readJson is not defined

こちらについては、ファイルの読み書き関数で取得した文字列をパースする、もしくはオブジェクトを文字列化する方法で対応することを示されています。

上でエラーになるコードは以下のように直します。

> const data = await JSON.parse(await Deno.readTextFile("data.json"));
undefined
> data
{ a: 123 }

JSON 専用の読み書き関数はあれば便利ではありますが、無いなら無いで対応しましょう。 削除経緯が記載されているような issue を見つけることはできませんでした。

deno run --watch

--watch を付与することで、Deno が実行しているアプリケーションに依存関係のあるファイルの変更を監視し、変更が行われると再起動する機能が追加されました

例えば、以下の簡単な Web サーバーのアプリケーションがあります。

[sample1.ts]

import { serve } from "https://deno.land/std@0.62.0/http/server.ts";

for await (const req of serve({ port: 8000 })) {
  req.respond({ body: "Hello World" });
}

こちらを起動するときに、以下のように--watchを以下のように付与して起動します。

deno run --allow-net --unstable --watch sample1.ts

アプリケーションを起動したまま、sample1.ts"Hello World"の部分を書き換え保存すると、以下のように表示が出ます。

Check file:///[ファイルの保管先ディレクトリのパス]/sample1.ts
Watcher File change detected! Restarting!

localhost:8000にアクセスすると出力結果が変わっているのが確認できます。 今回の確認では、十分に動作しているように感じましたが、まだ安定していない機能ということで先に示したように--unstableの付与も必要です。

変更監視してリスタートする機能は、Node.js であればnode-devの導入などにより行って来ましたが、Deno ではそれ単独でこういった開発機能までサポートしてくれようとしています。

Deno 1.5

Deno 1.5 での変更事項をDeno 1.5 リリースノートを元に確認します。

deno.land

バンドルの改善

バンドラーが、SWCをベースとした新しいものに変わっているとのことです。 このことによりパフォーマンスが、タイプチェック時に 3 倍、--no-checkのオプションを付与することで 15 倍になるということです。 加えて、バンドル後のサイズも 1.4 と比較して 35%低下するとのことです。

試しに、先に示した sample1.ts のソースをバンドルして比較してみます。

[sample1.ts]

import { serve } from "https://deno.land/std@0.62.0/http/server.ts";

for await (const req of serve({ port: 8000 })) {
  req.respond({ body: "Hello World" });
}

バンドルは、以下のコマンドで実行します。 deno bundle sample1.ts bundle.js

実行結果は以下の通りでした。

バージョン バンドル後サイズ
Deno 1.4 67.55 KB
Deno 1.5 42.45 KB

確かに、Deno 1.5 でバンドルしたものの方が Deno 1.4 でバンドルしたものに比べ、30%程度ファイルサイズが削減されました。

alart confirm prompt 関数の追加

Web プラットフォーム向け(要はブラウザ向け) にこれまで使っていた alert confirm prompt を deno1.5 に取り込んでいます。

例えば、以下のように使用できます。

[sample2.ts]

let input: number | null = null;

while (true) {
  const buf = prompt("数字を入力して:");
  if (!Number(buf)) {
    alert(`入力した [${buf}] は数字じゃ無いよ`);
    continue;
  }
  input = Number(buf);
  if (confirm(`本当に [${input}] で良いの?`)) {
    break;
  }
}

こちらをdeno run sample2.tsで実行すると以下のようになります。

$ deno run sample2.ts
Check [sample2.tsの保存先ディレクトリ]/sample2.ts
数字を入力して: s
入力した [s] は数字じゃ無いよ [Enter]
数字を入力して: 1
本当に [1] で良いの? [y/N] y
$

簡単にコンソールで入力を求める実装ができるのは助かるばかりです。

REPL が改善された

REPL(対話的動作)が改善されたことが挙げられています。

  • Tab キーの入力による補完
  • コンソールのシンタックスハイライト
  • トップレベル await のサポート

入力の補完により、REPL でちょっと動作を試す様なシチュエーションでの利便性が上がっていると感じます。

これらの他にも、deno lint の改善や、deno fmt が stable になったり、std 内のメソッドの変更や型定義チェックの追加がなされています。

deno 1.6

Deno 1.6 での変更事項をDeno 1.6 リリースノートを元に確認します。

deno.land

TypeScript 4.1 をサポート

Deno 1.6 から、最新の安定版である TypeScript 4.1 をサポートするようになりました。 TypeScript 4.1 のリリースノートによると、テンプレートリテラルタイプ などが導入されています。

deno compileの導入

これまでdeno bundle で typescript をバンドルして 1 つのファイルにまとめたり、deno installによりシェルに関連付けをしてきました。 新たに、ソースコードからスタンドアロンな依存のないバイナリを作成できるようになります。

先に示している sample1.ts からバイナリを作成してみます。

$ deno compile --unstable sample1.ts
Check [sample1.tsの保存先ディレクトリ]/sample1.ts
Bundle [sample1.tsの保存先ディレクトリ]/sample1.ts
Compile [sample1.tsの保存先ディレクトリ]/sample1.ts
Emit sample1
$ sample1 
#=> 簡単なwebサーバーが起動

独立したバイナリの実行により、samole1.ts の内容が実行される簡単な Web サーバーが起動しました。

上に示す通り、現在は実行するために--unstableの付与が必要な機能です。 短い期間で大きな変更のある可能性が示唆されているので、次のリリースにはまた様相が変わっているかもしれません。

CLI だけでなく、GUI で TypeScript で書かれたソースから作成されたアプリを配布するにも魅力的な機能だと感じます。

気になるのは、「内部はいったいどういうことになってるのだろう?」という点です。 なんとなく ビルドされた Electron みたいな感じ(Chromium を内部にもっている)だろうかと思いましたが、 こちらのプルリクに記述がありました。 https://github.com/denoland/deno/pull/8539

「現在のバイナリに、バンドルされたソースファイルと magic trailerを付け足して新しいバイナリを作る」とされていました。 (magic trailerが何を示すのかはよくわかりませんでした。ググると MTG の情報ばかり。) ということは親となる Deno 本体のバイナリよりも作成されたバイナリの方がファイルサイズは大きいはず、と思い確認しました。

ファイルサイズ(byte)
Deno1.6 48,779,678
新たに作成されたバイナリ 48,823,062

確かに作成されたバイナリの方が、Deno 本体よりファイルサイズが大きくなっていました。
スタンドアロンのバイナリの実行には不必要なものまで含めたバイナリになっていることへの対応も始まっているので、そのうちソースコードの内容次第では作成されたバイナリの方が小さくなる形に変わっていくでしょう。

先の通り、まだ--unstableをつける必要のある開発中機能であることもあり、制限があります。

  • Web ワーカーをサポートしていない
  • 動的にソースをインポートできない
  • V8 フラグとサンドボックス権限をカスタマイズできない

確かに、サンドボックスの部分については、deno run sample1.tsするためには--allow-netの付与が必要でしたが、コンパイルされたバイナリではつけずに起動できていました。

それぞれすでに issue が立っていますし、今後の計画も示されているので追々解決されるでしょう。 現在問題を抱えていても魅力的な機能だというのが正直な感想でした。

ビルトイン Deno 言語サーバー の追加

Deno1.6 にはdeno lspで実行できる Language ServerProtocol の実装が含まれています。
何をする機能なのかわかりにくいのですが、要はエディタでのコードの補完やヒントの表示などの高度な機能を提供するサーバーが起動できるということです。
例えば VSCode の Deno 向けの拡張機能は、deno lspに問い合わせて機能を提供できるということになるようです。

フォーマットの機能や、lint の機能を deno のバイナリそのものが提供してくれるので、エディタもそこを利用すようにするというのは当然の帰着かもしれません。

MacArm64 のサポート

M1 プロセッサ搭載の端末を Deno1.6 から、サポートするようになりました。
M1 プロセッサの搭載機を持っていないので確認できませんでした。

std/bytes 関数の名前が変更に

std/bytes モジュールが、オーバーホールされメソッド名が変更になりました Array の API と整合性を高めるための変更だそうです。

変更前 変更後
copyBytes copy
equal equals
findIndex indexOf
findLastIndex lastIndexOf
hasPrefix startsWith
hasSuffix endsWith

確認してみると、この変更は、std@80/bytes からの内容でした。std@79/bytes では、変更前の関数が定義されています。

deno.land / std@0.80.0 / bytes

deno.land / std@0.79.0 / bytes

確認してみましたが、以下のようにバージョンの指定しない場合には最新版が読み込まれるので、findIndex の定義が無くエラーになります。

import { findIndex } from "https://deno.land/std/bytes/mod.ts";

以下のように@0.79.0と指定してあげることで Deno1.6 でも変更前の関数名で呼び出しは可能でした。

import { findIndex } from "https://deno.land/std@0.79.0/bytes/mod.ts";

とはいえ、仮にバグが内在していても今後修正はされないわけですから、順次新しいものに切り替えていくのがいいと思います。
このように存在した関数が無くなるような破壊的な変更を想定し、本番運用をする環境で使うようなものは、各ライブラリのバージョンを指定して書いておくのがいいと感じます。

これら以外に、リリース前のバグフィックス版を取得できるオプションが増えていたりしました。


Deno 1.4 Deno 1.5 Deno 1.6 の機能を追加・変更の内容を見てきました。
Deno の機能がより良くなっていることがわかります。
特に、数字で見て取れるバンドルの改善などはわかりやすいものでした。
スタンドアロンバイナリの作成機能は、deno が単純な TypeScript の実行エンジンとしてだけでなく、成長していることがわかります。

次のリリースも追いかけていきたいと思います。

P.S

虎の穴ラボではいくつかのオンラインイベントを企画しております。是非ご参加ください!!

TORA LAB Management & Leader Meetup

12/23(金) 19:30からとらのあなが運営している「とらのあな通販」と「Fantia」の開発の魅力を発表し、参加いただいた方の気になる点やご質問に答えるイベントとなっています。 yumenosora.connpass.com

その他採用情報

虎の穴ラボでの開発に少しでも興味を持っていただけた方は、採用説明会やカジュアル面談という場でもっと深くお話しすることもできます。ぜひお気軽に申し込みいただければ幸いです。 カジュアル面談では虎の穴ラボのエンジニアが、開発プロセスの内容であったり、「今期何見ました?」といったオタクトークから業務の話まで何でもお応えします。 カジュアル面談や採用情報はこちらをご確認ください。 yumenosora.co.jp