@ twind/wmr - WMR utilizing @ twind/preact
Intro
休日寝っ転がりながらスマホいじっていたら、1年前に少し話題になったTwindという軽量版Tailwindをブクマしたまま放置していたことに気づいたので、ちょうど1年経つし少しやってみるかと思い、重い腰を上げて素振りした次第です。
TwindはCSSをCSS-in-JSで行うライブラリとツールでTemplate Literalを使ったクラスの生成するAPI、SSR向けにCSSファイルの作成、ビルド無しでTailwindクラスを利用するshimライブラリなどを提供するようです。
そんなことがはてなブックマークに書いてありました。azuさんmizchiさんありがとう。
やっていきます。
Start
Twindの思想はPreactにとても似ていたのでPreactと一緒に使うことにしました。
更にTwindを公開しているtw-in-jsのリポジトリを見ていくとWMRを使ったサンプルがあったのでWMRと一緒に使うことのできる@twind/wmrパッケージを導入します。
ただREADME.mdを見ても怪文書が書いてあるだけでCodeSandBoxで動いているサンプルもWMRのボイラープレートを使っていないので、WMRのボイラープレート優先でCodeSandBoxにあるコードを移植したボイラープレートを作成しましょう。
しました。
解説が面倒なので以降diffファイルを使います。
$ npm init wmr tw
$ cd tw
まずWMRボイラープレートでプロジェクトを作成します。
途中create-wmrを使用するか聞いてくるのでyを入力するなりyesコマンドをパイプで渡すなりして「はい」を選択します。
diff -ur -x package-lock.json -x node_modules wmr/package.json tw/package.json
--- wmr/package.json	2022-01-16 13:21:03.550069105 +0000
+++ tw/package.json	2022-01-16 12:24:55.000000000 +0000
@@ -1,16 +1,30 @@
 {
+	"name": "tw",
+	"version": "1.0.0",
 	"private": true,
+	"description": "Preact, Twind, WMR",
+	"main": "public/index.js",
 	"scripts": {
 		"start": "wmr",
 		"build": "wmr build --prerender",
-		"serve": "wmr serve"
+		"serve": "wmr serve",
+		"test": "echo \"Error: no test specified\" && exit 1"
 	},
 	"eslintConfig": {
 		"extends": "preact"
 	},
+	"keywords": [
+		"preact",
+		"twind",
+		"wmr"
+	],
+	"author": "黒ヰ樹",
+	"license": "MIT",
 	"dependencies": {
+		"@twind/wmr": "^1.0.9",
 		"preact": "^10.6.4",
-		"preact-iso": "^2.3.0"
+		"preact-iso": "^2.3.0",
+		"twind": "^0.16.16"
 	},
 	"devDependencies": {
 		"wmr": "^3.7.2"
package.jsonに最低限必要な情報を追加していきます。
$ npm i
$ mkdir public/pages/twind
$ touch public/pages/twind/index.js
Twindに関するパッケージが追加されます。
Twindに関するページも作っておきます。
diff -ur -x package-lock.json -x node_modules wmr/public/header.js tw/public/header.js
--- wmr/public/header.js	2022-01-16 13:21:02.369964304 +0000
+++ tw/public/header.js	2022-01-16 11:58:27.000000000 +0000
@@ -7,6 +7,7 @@
 			<nav>
 				<a href="/">Home</a>
 				<a href="/about">About</a>
+				<a href="/twind">Twind</a>
 				<a href="/error">Error</a>
 			</nav>
 			<label>
diff -ur -x package-lock.json -x node_modules wmr/public/index.js tw/public/index.js
とりあえずヘッダーにTwindページのリンクを生やします。
diff -ur -x package-lock.json -x node_modules wmr/public/index.js tw/public/index.js
--- wmr/public/index.js	2022-01-16 13:21:02.369964304 +0000
+++ tw/public/index.js	2022-01-16 13:24:57.694862846 +0000
@@ -1,9 +1,11 @@
-import { LocationProvider, Router, Route, lazy, ErrorBoundary, hydrate, prerender as ssr } from 'preact-iso';
+import { ErrorBoundary, LocationProvider, Route, Router, lazy } from 'preact-iso';
+import withTwind from "@twind/wmr";
 import Home from './pages/home/index.js';
 import NotFound from './pages/_404.js';
 import Header from './header.js';
 
 const About = lazy(() => import('./pages/about/index.js'));
+const Twind = lazy(() => import('./pages/twind/index.js'));
 
 export function App() {
 	return (
@@ -14,6 +16,7 @@
 					<Router>
 						<Route path="/" component={Home} />
 						<Route path="/about" component={About} />
+						<Route path="/twind" component={Twind} />
 						<Route default component={NotFound} />
 					</Router>
 				</ErrorBoundary>
@@ -22,8 +25,8 @@
 	);
 }
 
+const { hydrate, prerender } = withTwind(data => <App {...data} />);
+
 hydrate(<App />);
 
-export async function prerender(data) {
-	return await ssr(<App {...data} />);
-}
+export { prerender };
怪文書を参考にSSRを使わない方法へ変更して、withTwindを増やしておきます。
const Twind = () => (
	<section tw="h-screen bg-purple-400 flex items-center justify-center">
		<h1 tw="font-bold text(center 5xl white sm:gray-800 md:pink-700)">This is Twind!</h1>
	</section>
);
export default Twind;
public/pages/twind/index.jsにCodeSandBoxで動いているサンプルを参考にしてTwindページのコンポーネントを書きます。
$ npm start
起動します。

できました。
めでたしめでたし。
Outro
久々にJSXコンポーネント作ってnpmコマンド使ってやるやつやったので楽しかったです。
- ホットリロードに対応したTailwindを書けるので開発体験が良い。
 - ディレクトリ構成に癖がなく、HTML, CSS, JavaScriptを編集するだけなので初心者にも優しい。
 - WMRのボイラープレートはYAMLなど一部を除きインデントがタブ。思想が強い。
 - ReactやTailwindをそのまま動かすよりも軽くて早い。プロジェクトサイズはnode_modules含めて8MBぐらい。
 - 試しに
npm i typescriptしてみたらnode_modules含めて70MBになった。@twind/wmrでtypescriptはoptionalなので追加しなくても使える。 
Twind全く紹介していませんが終わります。
開発環境できたのでこれからTwind頑張るぞい。
P.S.
ところでGitpodってまたworkspaceのURLに使われるID変わったんですね。
オーナー名とリポジトリ名を使ったIDになっててびっくりした。
Discussion