🌪️

@ twind/wmr - WMR utilizing @ twind/preact

2022/01/16に公開

Intro

休日寝っ転がりながらスマホいじっていたら、1年前に少し話題になったTwindという軽量版Tailwindをブクマしたまま放置していたことに気づいたので、ちょうど1年経つし少しやってみるかと思い、重い腰を上げて素振りした次第です。

https://github.com/tw-in-js/twind

TwindはCSSをCSS-in-JSで行うライブラリとツールでTemplate Literalを使ったクラスの生成するAPI、SSR向けにCSSファイルの作成、ビルド無しでTailwindクラスを利用するshimライブラリなどを提供するようです。

https://b.hatena.ne.jp/entry/s/github.com/tw-in-js/twind

そんなことがはてなブックマークに書いてありました。azuさんmizchiさんありがとう。
やっていきます。

Start

Twindの思想はPreactにとても似ていたのでPreactと一緒に使うことにしました。
更にTwindを公開しているtw-in-jsのリポジトリを見ていくとWMRを使ったサンプルがあったのでWMRと一緒に使うことのできる@twind/wmrパッケージを導入します。

https://github.com/tw-in-js/use-twind-with/tree/main/packages/wmr

ただREADME.mdを見ても怪文書が書いてあるだけでCodeSandBoxで動いているサンプルもWMRのボイラープレートを使っていないので、WMRのボイラープレート優先でCodeSandBoxにあるコードを移植したボイラープレートを作成しましょう。

https://gitlab.com/tkithrta/tw

しました。
解説が面倒なので以降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

起動します。

tw

できました。
めでたしめでたし。

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