packup で スタイルが付いた React コンポーネントを取り扱う で Cloudscape を扱う記事を書いた。
その時はある程度できることをまとめたが、Fresh で動かす方法が分かったので、これもまた纏めてておきたい。
参考
Fresh With Cloudscape
参考にも載せている Issue で Fresh で MUI を使う方法について記述がある。
MUI の場合には、import map に次のような記述を試みている。
import_map.json1 2 3 4 5
| { "imports": { "@mui/material": "https://esm.sh/@mui/material@^5.10.17?alias=react:preact/compat,react/jsx-runtime:preact/compat/jsx-runtime&deps=preact@10.11.0" } }
|
これと同じことを Cloudscape に試してみる。
import_map.json1 2 3 4 5 6 7 8 9 10 11 12 13 14
| { "imports": { "$fresh/": "https://deno.land/x/fresh@1.1.3/", "preact": "https://esm.sh/preact@10.11.0", "preact/": "https://esm.sh/preact@10.11.0/", "preact-render-to-string": "https://esm.sh/*preact-render-to-string@5.2.4", "@preact/signals": "https://esm.sh/*@preact/signals@1.0.3", "@preact/signals-core": "https://esm.sh/*@preact/signals-core@1.0.1", "twind": "https://esm.sh/twind@0.16.17", "twind/": "https://esm.sh/twind@0.16.17/", "@cloudscape-design/components/button": "https://esm.sh/@cloudscape-design/components@^3.0.220/button?alias=react:preact/compat,react/jsx-runtime:preact/compat/jsx-runtime&deps=preact@10.11.0", "@cloudscape-design/components/badge": "https://esm.sh/@cloudscape-design/components@^3.0.220/badge?alias=react:preact/compat,react/jsx-runtime:preact/compat/jsx-runtime&deps=preact@10.11.0" } }
|
このように準備し、アプリケーション側で、コンポーネントを使用してみる。
Fresh 初期状態でのボタンを Cloudscape のボタンに差し替えて、バッチを仕込む。
routes/index.tsx1 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
| import { Head } from "$fresh/runtime.ts"; import Counter from "../islands/Counter.tsx"; import Button from "@cloudscape-design/components/button"; import Badge from "@cloudscape-design/components/badge";
export default function Index() { return ( <> <Head> <title>Fresh App</title> <link rel="stylesheet" href="https://esm.sh/@cloudscape-design/global-styles/index.css" ></link> <link rel="stylesheet" href="https://esm.sh/@cloudscape-design/components@^3.0.220/badge/styles.scoped.css" ></link> <link rel="stylesheet" href="https://esm.sh/@cloudscape-design/components@^3.0.220/button/styles.scoped.css" ></link> </Head> <div class="p-4 mx-auto max-w-screen-md"> <Counter start={3} /> </div> <div class="p-4 mx-auto max-w-screen-md"> <Button variant="primary">Click</Button> <Badge color="red">Badge</Badge> </div> </> ); }
|
island でもボタンとバッチを表示
islands/Counter.tsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import { useState } from "preact/hooks";
import Button from "@cloudscape-design/components/button"; import Badge from "@cloudscape-design/components/badge";
interface CounterProps { start: number; }
export default function Counter(props: CounterProps) { const [count, setCount] = useState(props.start); return ( <div class="flex gap-2 w-full"> <p class="flex-grow-1 font-bold text-xl">{count}</p> <Button variant="primary" onClick={() => setCount(count - 1)}> -1 </Button> <Button variant="primary" onClick={() => setCount(count + 1)}> +1 </Button> <Badge color="blue">Badge</Badge> </div> ); }
|
これを起動すると、次の様に表示/動作する。
というわけで、いい具合で SSR でも CSR でもちゃんと動作する。
いくつかポイントがある。
- コンポーネントの CSS を直接ロードさせる
Head に https://esm.sh/@cloudscape-design/components@^3.0.220/[コンポーネント名]/styles.scoped.css
を直接読ませる。
これをやらないと、スタイルが適用されない。
- islands で使うコンポーネントの CSS も SSR 側で読んでおく
alias=react:preact/compat~~~ is 何?
esm.sh が提供している依存関係のエイリアス機能。
依存先が react だった場合、それを preact に切り替えることができる。
切り替えたことで、preact が使われている Fresh とも協調できる。
起動時間が長くなる
denoland/import_map - Issues - Import Maps don’t support package address targets with query parameters という Issues が立っている。
クエリパラメータが有るのを仕様的には許容していない様子。
また、起動の都度 https://esm.sh/v110/@cloudscape-design/components@3.0.220/X-YS9yZWFjdC9qc3gtcnVudGltZTpwcmVhY3QvY29tcGF0L2pzeC1 ydW50aW1lLHJlYWN0OnByZWFjdC9jb21wYXQKZC9wcmVhY3RAMTAuMTEuMA/internal/base-component/styles.css
が毎回ダウンロードされている。
これのせいもあるのか、普段の Fresh から比べると起動時間が非常に長くなってしまった。
ある程度、起動しっぱなしにできるなら起動時間が遅いのは許容できるが、deno deploy で動かすなら苦しいところが出てきそう。
常に起動が維持しておけるなら問題はなさそう。
一定間隔で、API を叩いてスタンバイさせておくというのは考えられるけど、Deno.inc からすると歓迎し難い可能性はある。
では。