Deno向けに静的サイトジェネレーターを作ってみた!
- 2023/10/07 更新
はじめに
ブンブン🐝ハロー・・・という冗談はさておき、Deno用に静的サイトジェネレーターというものを作ってみた。
機能の概要と工夫した所とかを書いていくよ。
(Denoの静的サイトジェネレーターってlume以外にウワサを聴いたことがない気がする)
名前はなんなんだい
Dejamuって名前をつけてみました。
名前の由来は筆者がよく見る予知夢から(´・ω・`)
そのまま使うよりちょっといじったほうがユニークになるよね。
以下はDejamuのリポジトリへのリンクです。
この記事を書いてる時点で、バージョン 0.0.14
ですね。
最近まで雑に書いてたのでコミット履歴とかが悲惨なことになってるよ。
機能
Preactを使って簡単に静的なサイトを作れるよ。
- Markdown
- PostCSS
に対応してるので、すこし遊べるかも。
Markdownはmarkedjsを使っていて、特にこれといった機能はないです。(´・ω・`)
lumeとの違い
lumeはいろんな書き方(nunjucksとかjsx)に対応してるけど、Dejamuはpreact一筋だよ。
初期化スクリプト
これから Dejamu を始めるぜ!って人向けに現在のディレクトリにプロジェクトを作ってくれるやつを用意しているよ。
deno run -rA https://raw.githubusercontent.com/ikasoba/dejamu/main/scripts/init.ts
ってやると、最新のバージョンで遊べるよ。
deno task serve
とかでサーバーを立ち上げたり、deno task build
でビルドしたりできるよ。
Deno.landにはまだ怖くてうpしてないよ。
設定ファイル
使う人には dejamu.config.ts
というファイルに設定を書いてもらいます。
初期化スクリプトを実行した場合はこんな風になってるよ。
import type { Config } from "dejamu/mod.ts";
import PreactPlugin from "dejamu/plugins/preact/mod.ts";
import MarkdownPlugin from "dejamu/plugins/md/mod.ts";
export default {
entryPoints: ["pages/*.{jsx,tsx,md}"],
plugins: [
PreactPlugin(),
// このlayoutsは後で解説するよ
MarkdownPlugin("layouts/"),
],
} satisfies Config;
pages直下にjsx
とか作れば読んでくれるらしい。
PostCSSを使うならこう書き足してね。
import type { Config } from "dejamu/mod.ts";
import PreactPlugin from "dejamu/plugins/preact/mod.ts";
import MarkdownPlugin from "dejamu/plugins/md/mod.ts";
import PostCssPlugin from "dejamu/plugins/postcss/mod.ts";
export default {
entryPoints: [
"pages/*.{jsx,tsx,md}",
// styles直下に置くことが多いので適当に
"styles/*.css"
],
plugins: [
PreactPlugin(),
MarkdownPlugin("layouts/"),
// ".css" という拡張子のファイルをpostcssで処理させるよ。
// 配列なので他の拡張子(scssとか)も足せるよ。
// 第2引数にpostcss用のプラグインを配列で渡せたりするよ。
PostCssPlugin([".css"])
],
} satisfies Config;
Markdownを使う時のポイント
pages配下にmarkdownを作ったら動くよ。
layoutという機能でデザインを使いまわしたりできるよ。
以下はlayoutの例だよ。
import { Head } from "dejamu/mod.ts";
import { Markdown } from "dejamu/plugins/md/Markdown.tsx";
import type { LayoutComponent } from "dejamu/plugins/md/MarkdownPlugin.tsx";
export default (function HogePage({ children }) {
return (
<>
<Head>
<meta name="viewport" content="width=device-width,initial-scale=1" />
<link
rel="stylesheet"
href={
// この projectRoot は特殊なグローバル変数で、相対パスでプロジェクトのルート(dejamu.config.tsがあるところ)を示すようになってるよ。
// ビルドするときに動的に変わるので安心して使ってね。
`${projectRoot}/styles/index.css`}
/>
<title>ほげほげサイト</title>
</Head>
<Markdown>
{children}
</Markdown>
</>
);
}) satisfies LayoutComponent;
こっちは、layoutを使うmarkdownの例
---
# MarkdownPluginの引数で渡したディレクトリが基準だよ。
# デフォルトでは layouts/
# 豆知識: ここを消すと、内部で用意してある空っぽのlayoutにフォールバックされるよ
layout: HogePage.tsx
---
ここに内容
工夫したところ
はい、工夫しました。
試作した時、そこそこページの読み込みが遅かったのでパフォーマンスを良くしました。
アイランドアーキテクチャという、なんかすごい横文字のアレをdenoのfreshくんは採用しています。
これは、必要なJSだけクライアントに読ませることで高速化するぜ!みたいなやつっぽいですね。
自作のソフトが遅いのは嫌なので、それを採用してみました。
ファイル名を *.islands.tsx
みたいな形式にするとHooksとかが使えるようになります。
JSだったら *.islands.jsx
です。
下に書いてあるような雰囲気で書けるよ。
import { useState } from "npm:preact/hooks";
export default function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount((count) => count + 1)}>
{count == 0 ? "click me!" : `count: ${count}`}
</button>
);
}
得た知見
⚠ これはふんわりした頭で得た知見なので間違ってる可能性が大きいです。
freshは、 preact
のOption Hooks
で公開されてないフックを使ってislandsなコンポーネントをいい感じにビルドできるようにしてるみたいだったよ。
ここらへんとか
__r
とか__b
とか・・・よくわからん・・・。
これは他人のコードを見ない限りなんなのかさっぱりだから僕も勘で書いてるよ。
感想
たのしかった。
勢いで書いたので雑になってるかも、ごめんね。
Discussion