preactとesbuildを使ってみた

preactを選んだ動機

最近、react…というかJSXの練習をしてみたいと思うようになりました。HTML文をTypescriptのコードの中で作成して、div要素のinnerHTMLを書き換えて…という作業が結構大変だなぁ~と感じるようになってきたのです。JSXとかを使えばそれが楽になるのかな?という安直な考えです。

そこで、まずは本家のreactをちょこちょこ触ってみたのですが、どうにも自分には合わない感じがしました。

「自分が作ったコード+reactに必要で付加されるコード=生成されるJavascript」となるのですが、自分で作った部分より明らかに大きくなっていて、なんか違う感が強かったのです。

また、やりたいことは「div要素のinnerHTMLを書き換えて…」の部分なので、その目的にはちょっと大げさすぎるかな…と感じたのでした。

そこでいろいろと調べ見たところ、preactというreactの簡易版的なものにたどり着きました。コードを書く時の作法(useStateなどのフックを使うところ)などはreactと似たような使い方をするみたいですし、簡単そうなのでこれを使ってみることにしました。

esbuildを選んだ動機

じつはwebpackを使うのはあまり好きでなく、最近はずっとtsc(TypeScriptトランスパイラ)だけを使っていました。

tscオンリーだとモジュールをimportするようなコードはうまくトランスパイルできません。

しかしrefernce pathを使うことで、適度にソースファイルを分けしつつ、

/// <reference path="Parameter.ts" />
/// <reference path="Data.ts" />

// ParameterやDataを参照するコードは以下に記載していく…。

のような書き方で連結するだけでも、個人の趣味のプログラムレベルなら十分なのです。(ソースコードは少ないですし。)

webpackを使っていなかった理由は2つあって、1つ目はやっぱり遅すぎる点です。tscなら1秒かからないものが1分近くかかるのは、ちょっと…。

理由2つ目は、環境周りのセッティングが面倒だったこと。

毎回、

npm i -D webpack webpack-cli ts-loader

のようなセッティングをして環境を作るのは面倒なうえに、node_module/以下にいろいろファイルが作られていくのも大変でした。

webpack.config.jsのセッティングもすぐ忘れてしまうので、毎回ネット検索してしまうし…。

というわけでwebpackは使いたくない!

だけど、preactを使うには、reference pathでつなげるのではなく、モジュールimportしてバンドルする必要がある!

という理由で、これまたいろいろと調べた結果、esbuildにたどり着きました。噂通りに早くて、tscでトランスパイルするのとほとんど変わりません。

かんたんに環境構築の例

簡単な環境構築例としてハローワールドしてみます。

esbuildインストール

esbuildはグローバルインストールしています。

npm install -g esbuild

preactのインストールと設定

新たにHelloWorld用のディレクトリを作成して、vscodeで開いて、preactをローカルインストールします。

npm install -D preact

Typescriptソースコードを置く場所として、srcを作成します。

mkdir src

そして、tsconfig.jsonを下のようにします。

{
  "compilerOptions": {
    // for build
    "module": "CommonJS",
    "jsx": "react-jsx",
    "jsxImportSource": "preact",
    "skipLibCheck": true,
    "baseUrl": "./",
    // for check
    "strict": true,
    "noEmit": true,
    "noImplicitOverride": true,
    "newLine": "crlf",
    "target": "ES2020",
    "isolatedModules": true,
    "esModuleInterop": true,
  },
  "include": [
    "src/**/*",
  ]
}

HTMLを作成する

ブラウザで表示するために、test.htmlを下のように作ります。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="test.js"></script>
    <title>Test</title>
</head>

<body>
    <div id="root"></div>
</body>

</html>

id="root"に対してpreactでレンダリングを行うつもりです。

TypeScriptのソース

src/test.tsxを次のように作ります。

import { render } from "preact";

window.addEventListener('DOMContentLoaded', () => {
    const element = document.getElementById('root');
    if (element) {
        render(<Hello />, element);
    }
})

function Hello() {
    return (
        <p>Hello, world!</p>
    )
}

esbuildでトランスパイル

下のようにesbuildでトランスパイルします。

 esbuild --bundle src/test.tsx --outdir=.

これですべての作業が終わったので、後は結果を見るだけです。test.htmlをブラウザで開けば、

Hello, world!

と表示されます。

google chromeのデベロッパーツールで見てみると、

<div id="root"><p>Hello, world!</p></div>

のようになっていました。

コメント