LoginSignup
73
65

More than 3 years have passed since last update.

Deno+HTMLで手軽にGUIアプリを作る

Last updated at Posted at 2020-05-31

はじめに

carolという、DenoとHTMLを使ってGUIアプリを作るためのモジュールを作成しました。
この記事では、その紹介も兼ねてcarolを使ったGUIアプリの作成方法について解説します。

前提条件

以下の環境で動作確認しています。

  • Deno v1.0.3
  • Google Chrome v83.0.4103.61

carolはUIを提供するために、ローカルにインストールされたGoogle Chromeを使用します。
そのため、事前にChromeをインストールしておく必要があります。

Hello World!

まず、以下のようなスクリプトを用意します。

mod.ts
import { launch } from "https://deno.land/x/carol@v0.0.6/mod.ts";
import { dirname, join } from "https://deno.land/std@0.54.0/path/mod.ts";

const app = await launch({
  title: "Hello Deno!",
  width: 480,
  height: 320,
});

// Chromeが終了したらDenoのプロセスも終了させる
app.onExit().then(() => Deno.exit(0));

// Chrome側に関数を公開する
await app.exposeFunction("greet", (name: string) => `Hello, ${name}!`);

const folder = join(dirname(new URL(import.meta.url).pathname), "public");
app.serveFolder(folder); // "./public"ディレクトリ配下からファイルを配信する
await app.load("index.html"); // "./public/index.html"を読み込む

次に、上記のmod.tsと同一ディレクトリにpublicディレクトリを作成し、その中にChromeから読み込むHTMLとJSファイルを用意します。

public/index.html
<html>
  <head>
    <meta charset="utf-8" />
  </head>
  <body>
    <h2>Hello, Deno!</h2>
    <script src="/index.js" type="module">
    </script>
  </body>
</html>
public/index.js
(async () => {
  window.alert(await window.greet("Deno"));
})();

この時点で以下のようなディレクトリ構造になっている想定です。

/
├── mod.ts
└── public
    ├── index.html
    └── index.js

それでは、mod.tsを実行してみます。

$ deno run --allow-env --allow-net --allow-read --allow-write --allow-run ./mod.ts

以下のように表示されれば成功です。

Screenshot.png

解説

先程のmod.tsの内容について解説します。

launch()

launch関数を実行すると、Chromeが起動します。
width及びheightプロパティでWindowの横幅と縦幅を指定できます。

import { launch } from "https://deno.land/x/carol@v0.0.6/mod.ts";

const app = await launch({
  title: "Hello Deno!",
  width: 480,
  height: 320,
});

また、argsプロパティを指定することで、Chromeを起動する際のコマンドライン引数をカスタマイズできます。

例) Chromeをヘッドレスモードで起動する
const app = await launch({ args: ["--headless"] });

app.onExit()

// Chromeが終了したらDenoのプロセスも終了させる
app.onExit().then(() => Deno.exit(0));

app.onExitPromiseを返却します。
このPromiseはChromeが終了した際にresolveされます。
上記コードでは、Chromeの終了に合わせてDenoのプロセスも終了させています。

app.exposeFunction(name, fn)

// Chrome側に関数を公開する
await app.exposeFunction("greet", (name: string) => `Hello, ${name}!`);

app.exposeFunction()を使うと、DenoからChromeへ関数を公開できます。
第1引数はChrome側から参照する際の関数名、第2引数で公開する関数の処理を記述します。

公開した関数はwindowオブジェクト経由で使用することができます。

例えば、上記コードの場合、windowオブジェクトにgreet関数が追加されます。

// 以下はブラウザ上で実行されるJavaScriptコードの想定
(async () => {
  const result = await window.greet("Deno"); // Promiseが解決されると、関数の戻り値が取得できます。
  window.alert(result); // Hello, Deno!
})();

app.load()

ChromeにHTMLをロードさせる際に使います。

例えば、以下の例では、app.serveFolder()と組み合わせて、public/index.htmlをChromeに読み込むように指示しています。

const folder = join(dirname(new URL(import.meta.url).pathname), "public");
app.serveFolder(folder); // "./public"ディレクトリ配下からファイルを配信する
await app.load("index.html"); // "./public/index.html"を読み込む

また、以下のようにURLを直接指定することも可能です。

await app.load("https://www.google.co.jp/"); // ChromeにGoogleのトップページを読み込ませる

終わりに

DenoとHTMLを使ってGUIアプリを作る方法について解説しました。

興味があれば、是非使ってみてください。

また、Denoには他にもdeno_webviewというGUIライブラリがあるので、そちらもおすすめです。

補足

  • carolの名前の由来はcarlolorcaのアナグラムです。
  • carolのライセンスはMITライセンスです。
  • carlolorcaのソースをベースにしている箇所があり、そちらについては個別にライセンス・コピーライトが適用されます。
    • carloのライセンスはApache v2です(2020/05/31現在)
    • lorcaのライセンスはMITです(2020/05/31現在)
73
65
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
73
65