FORCIA CUBEフォルシアの情報を多面的に発信するブログ

初学者が手探りでOSS(Deno)に触れてみたら楽しかった話

2020.12.04

アドベントカレンダー2020 テクノロジー

事業開発部の田中です。業務ではwebコネクトの開発・保守に携わっています。
Node.jsを基盤とし、フロントはReact+Redux+Next.js、サーバーサイドはExpress.jsを利用し、TypeScriptで開発を進めています。

OSS(Deno)を触りたくなった動機

2020年5月にDeno 1.0.0がリリースされたのを受け、Twitterや様々な技術ブログでそれが注目されているのを知りました。

初学者(webエンジニア歴約1年)の私には、何か難しいことが議論されているな、立ち入るのはハードルが高そうだなと感想を持つのみでした。しかし、ふと公式Denoのプロジェクトにアクセスしてみると・・・。 

そう、ロゴがとても可愛いのです。

image.png

出典:Deno公式ArtWork

そこで興味が湧き、少し調べていると、業務で使用しているNode.jsと深く関連があること、やはりロゴが可愛いことから、触ってみようと思いました。 (ロゴの創作コミュニティも活発であり、ArtWorkが公式サイトにいくつも掲載されています。)

Denoとは

多くの記事やブログで取り上げられているため、詳しく記載することは省きますが、Denoは、Node.jsの制作者であるRyan Dahl氏がNodeでの反省点に基づき立ち上げた、新しいJavaScript / TypeScriptランタイムのプロジェクトです。そのため、公式Documentや解説記事ではNodeと比較し、Denoが特徴づけられていることが多いです。

Nodeとの大きな違いとして、以下がよく挙げられています。

  • npmを使用しないこと
  • Denoはpackage.jsonを使用しないこと
  • URLまたはファイルパスとしてモジュールを参照すること
  • すべての非同期処理はPromiseで表現されること
  • 明示的に許可しないかぎり、ネットワーク接続やファイル読み取りができないこと
  • ES modulesを使用し、require()が使えないこと

実際に触ってみて楽しかったこと

マニュアルや基本的解説で手を動かす

Denoを学ぶにあたり、公式マニュアルや、日本語で解説されているDenoBookを読み解きました。マニュアルということもあり、かなり基本的なところから、また多くがNodeと比較しつつ丁寧に解説されています。 しかし初学者の私は、比較対象のそもそものNode機能の名称や処理を理解できておらず(NodeのStreamやhttp-server等)、知らない単語をひとつひとつ調べながら手を動かしました。

手を動かしている内に、業務で使用しているNodeで何が処理されていたのか、Denoを学びながら理解を深めることができました。

手探り感が楽しい

検索してヒットする記事では、1年前の記事の通りに実装してみても動作しなかったり、解説されているコマンドが使用できなかったりしました。

例えば、2020年11月時点最新のdeno.1.5 環境において、過去の記事をもとに以下を実行すると・・・
(Denoでは、TypeScriptをそのまま実行できるのです。)

console.log("hello");
deno hello.ts

実行結果

error: Found argument 'hello.ts' which wasn't expected, or isn't valid in this context
USAGE:
    deno [OPTIONS] [SUBCOMMAND]
For more information try --help

エラーとなってしまいます。正しく動作させるには、

deno run hello.ts

としなければなりません。そう、使用できるコマンドが変わってしまっているため、新しいものを使用しなければならないのです。

コマンドのヘルプを見ればすぐに正しいコマンドがわかるのですが、Denoでは今現在も破壊的な変更が加えられていっており、日々のキャッチアップが必須です。 昨年リリースされた記事の内容がそのまま使える、また昨日使えていた機能がそのまま使える保証はないようです。 一方、それだけの速度で開発が進められているので、開発速度を一端を感じられるのはとても新鮮な体験でした。

さらに、Deno特有のURL参照でモジュールを使用する関係上、以下のことも起きます。

先述のDeno 1.5.2環境にて、以下のようなソース(httpサーバの立ち上げ)を実行するとします。ポイントはDenoの標準モジュールであるserveをimportする際、URL指定になっている点です。

import { serve } from "https://deno.land/std@0.55.0/http/server.ts";
const s = serve({ port: 8000 });
console.log("http://localhost:8000/");
for await (const req of s) {
  req.respond({ body: "Hello World\n" });
}

上記ソースを以下のとおり実行してみると・・・ (Denoではネットワークとの通信、またファイルの読込が全てセキュアであり、deno runだけを実行するとモジュールの取り込みでエラーになってしまいます。モジュールの取り込みを明示的に許可する必要があるので --allow-netを付与しています。)

$ deno run --allow-net httpServer.ts
error: TS2345 [ERROR]: Argument of type 'string | URL' is not assignable to parameter of type 'string'.
  Type 'URL' is not assignable to type 'string'.
  return new URL(url).pathname
                 ~~~
    at https://deno.land/std@0.55.0/path/win32.ts:917:18
TS2345 [ERROR]: Argument of type 'string | URL' is not assignable to parameter of type 'string'.
  Type 'URL' is not assignable to type 'string'.
  return new URL(url).pathname;
                 ~~~
    at https://deno.land/std@0.55.0/path/posix.ts:438:18
Found 2 errors.

インターネットで検索して出てくるコードをそのままコピペして実行するだけでは、TypeScriptの型チェックで怒られてしまいました(またDeno1.0.0リリース当時の公式マニュアルにも記載があったものでもあります)。
正しく動作させるには、標準モジュールのserveのバージョンを、インストールされているDeno環境に対応するものにする必要があります(もちろんDeno 1.0.0環境に戻すことで先述のコードは動作します)。

import { serve } from "https://deno.land/std@0.79.0/http/server.ts";
const s = serve({ port: 8000 });
console.log("http://localhost:8000/");
for await (const req of s) {
  req.respond({ body: "Hello World\n" });
}

ちなみに、修正前の std@0.55.0はDeno1.0.0がリリースされた2020年5月当時のバージョンです。

わずか半年前のコードが動かない、そんなスピード感で開発が進められています。Deno関連のソースコードを追ってみる際も、新しいバージョンとなると、ディレクトリ構造から変わっている場合があり、GitHubレポジトリを探検することになります。

そんな開発の速さをリリースノートを追って体感しつつ、探検しながらコードを書くのは、一種のゲーム要素すら感じられ、とても楽しいものでした。

まとめ

初学者である私が、ロゴが可愛いという理由でOSSに触れてみましたが、体験したことのない文化に触れることができると共に、普段開発業務で用いている技術への根本的な理解を深めることができ、とても有意義な体験でした。

注目されているDenoですが、まだまだ実用化には機能追加が必要であり、また自身の技術と理解を深めるべく、 ぜひコントリビュートしていきたいと思います。

この記事を書いた人

田中 柾伎

事業開発部所属。
OSSを調べて動くコードを書くのは、固定ギア自転車のペダルを回す気分と全く一緒だと思いました。