Deno 環境で React アプリを作ってみる(Ultra)

前回、Deno で Vue.js アプリを作れないか試しましたが vue-router を組み込めなかったりと考えていたよりも上手く行きませんでした。
今回は、React アプリの開発ができる Ultra を試してみます。
React 経験ほぼ 0 ですが、試してみます。

参考

導入

とりあえず、ボイラープレートがあるのでクローンして、使ってみます。

1
2
3
4
5
git clone git@github.com:exhibitionist-digital/ultra.git

cd ultra/examples/boilerplate

make dev

Hello World とよく見るようなページが表示されます。

ディレクトリを眺める

ボイラープレートのディレクトリを眺めてみます。

1
2
3
4
5
6
7
8
.
|-- README.md
|-- importmap.json
|-- makefile
|-- server.js
|-- src
| `-- app.jsx
`-- tsconfig.json

相変わらず、 Deno のディレクトリは素直になりますね。

実装

今度こそできるか「ルーティング」ということで、react-router-dom を導入してみます。
Ultraでは、importmapを使用するので書き換えます。

importmap.json
1
2
3
4
5
6
7
8
9
10
11
12
{
"imports": {
"react": "https://esm.sh/react@18.0.0-alpha-bc9bb87c2-20210917?no-check",
"react-dom": "https://esm.sh/react-dom@18.0.0-alpha-bc9bb87c2-20210917?no-check",
"react-dom/server": "https://esm.sh/react-dom@18.0.0-alpha-bc9bb87c2-20210917/server?no-check",
"helmet": "https://esm.sh/react-helmet-async?deps=react@18.0.0-alpha-bc9bb87c2-20210917&bundle&no-check",
"wouter": "https://esm.sh/wouter?deps=react@18.0.0-alpha-bc9bb87c2-20210917&bundle&no-check",
"swr": "https://esm.sh/swr@1.0.0?deps=react@18.0.0-alpha-bc9bb87c2-20210917&bundle&no-check",
"ultra/cache": "https://deno.land/x/ultra@v0.3/cache.js",
"react-router-dom": "https://cdn.skypack.dev/react-router-dom" // <=追加
}
}

skypackから配信されるものを使用してみます。

簡単に子コンポーネントを作ってみます。

src/index.jsx
1
2
3
4
5
6
7
8
9
10
11
import React from "react";

const Index = () => {
return (
<main>
<span>Index</span>
</main>
);
};

export default Index;

ルーター自体を導入する src/app.jsx は以下のようにします。

src/app.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import { Helmet } from "helmet";
import React from "react";

import {
Link,
MemoryRouter,
BrowserRouter,
Switch,
Route,
} from "react-router-dom";

import Index from "./index.jsx";

// SSR 環境では、Windowオブジェクトを持たないためにエラーとなるので、どちらを使うのか選ぶ
const navigator = window && window.navigator && window.navigator.userAgent;
const isBrowser =
typeof navigator !== "undefined" && navigator.indexOf("Node.js") === -1;
const Router = isBrowser ? BrowserRouter : MemoryRouter;

const Ultra = () => {
return (
<Router>
<div>
<Helmet>
<title>ULTRA</title>
</Helmet>
<main>
<h1>Hello World</h1>
</main>
<div>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</div>
<div>
<Switch>
<Route path="/about">About</Route>
<Route path="/">
<Index />
</Route>
</Switch>
</div>
</div>
</Router>
);
};

export default Ultra;

(jsxは、シンタックスハイライトが崩れるなぁ)

Router を、BrowserRouter だけで使用すると window オブジェクトがないため、SSR時にエラーとなります。
MemoryRouter を使うと、エラーにならないということを確認して、調べた結果として参考資料を見つけました。
内容は Deno 環境用に多少調整して動作確認ができました。

改めて起動すると次のようになります。

パスルーティングがちゃんと行えました。
SSRもされているので、リロードしても問題なく動作します。

Ultra、Deno 環境でフロントエンド開発にすごく良さそうです。

Deno で React アプリを簡単に作ってみました。
React ほぼ初体験の状態でも、調べつつでもできたのはよかったです。
Ultra 自体の開発体験が、すごく良いというのがその理由になっていると感じます。

ボイラープレートだけ、取得して展開するツールをそのうち作ることになりそうです。

ではでは。