こんにちは。すずともです。
Deno拡張機能を有効にすると、.js
、.ts
などのファイルでDenoのLangage Serverが働くようになります。
Denoのプログラムを書く上でこれは便利な機能なのですが、ホームページを構築しようと埋め込み用のJavascriptファイルを作ると、そのファイルでもDenoの拡張機能が働いてしまいます。
Denoが働いてる環境でホームページ書くことなんてあるの?と思うかもしれませんが、サーバを立ててホームページを公開するときにDenoを使うと便利なんです。
今回の実験に使ったファイルはGithubにあげてありますので、作るのめんどくさい人はcloneしてくださいな。
kamekyame/serve-static-deno - Github
ホームページを公開するだけのサーバを立てる
servestと呼ばれるモジュールを使うと簡単に作れます。
以下のコードをコピペして実行するだけです。ちなみにこのコードはservestの公式HPから持ってきたものです。
Host static files
import { createApp, serveStatic } from "https://deno.land/x/servest@v1.3.1/mod.ts";
const app = createApp();
app.use(serveStatic("./public"));
app.listen({ port: 8899 });
上記のコードでは、serveStatic
関数に./public
と入れることで、publicフォルダ内のファイルを静的ファイルとして提供します。つまり、publicフォルダ内にindex.htmlやjs、cssなどをまとめておけば、http://localhost:8899 でホームページを公開するサーバとなるわけです。
公開するホームページでDOM操作をしてみる。
index.html
は適当に作るとして、そのなかでmain.js
を読み込み、title
というIDのついたH1タグの中身を変更するとしましょう。ファイル構成はこんな感じですかね。
serve-static-deno
├ .vscode
│ └ settings.json
├ main.ts
└ public
├ index.html
└ main.js
一応index.htmlも載せておきます。
<!DOCTYPE html>
<html lang="jp">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 id="title"></h1>
<script type="module" src="main.js"></script>
</body>
</html>
main.jsは
const title = document.getElementById("title");
title.textContent = "Hello!";
単純なやつですね。
実際に上記のファイル構成で作ってみると、たぶん、main.js
のdocumentの所がこんな感じになっていると思います。
※マウスカーソルが見えてませんが、documentの文字の上に載せてます。
document
がany
になっていますね。つまり、documentの補完をしてくれません。これだと、getElementbyID
みたいな打ち間違えも多くなっちゃいます。(特にdom関係の関数名は長いですからね笑)
ちなみに、HTML内にscriptタグを作ってjsを書くと、Document
型と判断してくれていることが分かります。htmlファイルはDenoの監視下ではないので、補完してくれるというわけですね。
documentの補完のおまじない
なぜdocumentがanyになるか。それは、Denoのプログラムではdocumentが使えないからです。だってDOM操作をする先がないんですからね笑
DenoにはTypescriptのコンパイラがついているのですが、そこでdocumentの補完を無効にしています。
無効にしているだけで、有効にすれば補完ができるというわけです!
ってことで、補完を有効にしたいファイルの先頭に以下のおまじないを付けてください!
/// <reference lib="dom"/>
ただのコメント分じゃん!って思うかもしれませんが、Typescriptのコンパイラは3つスラッシュのコメントを読んでくれるようです。
おまじないによって、補完が効きましたね!
おまじないの意味
ここからはおまじないの意味までちゃんと知っておきたい!っていうコアな人?(最近使えればいいやって人多くない?)向けの情報です。
Typescriptの公式リファレンスにちゃんと載ってます。
Triple-Slash Directicves
typescriptでは、コンパイラオプションにlib
ってのを渡すことで、どの型定義、構文を使うかを指定しています。
ってことで、documentを補完してほしかったらlib="dom"
を追加しているってわけです。
ちなみに、Deno内部では独自ライブラリdeno.window
っていうのを使用しているらしく、これでdocumentの部分などDenoに関係ない部分を消しているんですね。
不安定だから気を付けてね
main.js
に先ほどのおまじないを追加すればいいわけですが、vscodeの拡張機能はそこまで賢くないらしく、関係ないファイルにまでdocumentの補完をしてくれちゃってますw
まぁ、リアルタイムでチェックしてくれてるのに1ファイルだけ使うライブラリが違うって無茶苦茶ですからね笑
↑サーバ側のmain.ts
ファイル、documentを補完してしまっている。
なので、誤ってdocument.~を使わないように!
とはいっても、実行時に走るちゃんとした?コンパイラにはエラー吐かれる(tsファイルなら)のでまぁ安心ですね。
error: TS2584 [ERROR]: Cannot find name 'document'. Do you need to change your target library? Try changing the
lib
compiler option to include 'dom'.
document.body;
コンパイラのlib
オプションにdom
がないから入れたらどう?(意訳)
終わりに
最後まで記事を読んでくださりありがとうございました🙇
Denoはまだまだ奥が深く、僕はtypescriptもDenoから学んだので、知識も浅いです。
浅いなりにoutputしていこうかなということで記事を書いています!
言い回しが分かりにくかったり、間違った意味で言葉を使ったりしていたら教えてくれるとありがたいです。
これからもDeno、バンバンつかっていろんな記事書いていきますので、よろしくお願いします。