Freshで静的サイトを作る
はじめに
ただ、少し工夫をすると、静的なWebページを作れるのではないかと思い、試してみました。
前提
やりたいこと
Markdownのレンダリングは
routes/index.tsx
でカスタムハンドラを用意して行っています。
routes/index.tsximport { Head } from "$fresh/runtime.ts";
import type { Handlers, PageProps } from "$fresh/server.ts";
import { CSS, render as renderGFM } from "https://deno.land/x/gfm@0.2.3/mod.ts";
const gfmStyle = `
.markdown-body ul { list-style: disc }
.markdown-body a { color: teal }
${CSS}`;
export const handler: Handlers = {
async GET(req, ctx) {
// README.mdをHTMLへ変換します。
const url = new URL("../README.md", import.meta.url);
const markdown = await Deno.readTextFile(url);
const content = renderGFM(markdown, {});
// 下記のIndexコンポーネントをレンダリングします。
return ctx.render(content);
},
};
export default function Index(props: PageProps<string>) {
return (
<>
<Head>
<title>Awesome Fresh</title>
<style id="gfm">{gfmStyle}</style>
</Head>
<main
data-color-mode="auto"
data-dark-theme="dark"
class="p-4 mx-auto max-w-screen-md markdown-body"
dangerouslySetInnerHTML={{ __html: props.data }}
/>
</>
);
}
build.ts// Fresh v1.1.5時点では、`DENO_DEPLOYMENT_ID`の有無によって本番or開発環境の判断が行われます。
// ここでは、本番環境と同様の方法でレンダリングを行ってほしいため、手動で`DENO_DEPLOYMENT_ID`を設定しています。
const { stdout: gitOutput } = await new Deno.Command("git", {
args: ["rev-parse", "HEAD"],
}).output();
const revision = new TextDecoder().decode(gitOutput).trim();
Deno.env.set("DENO_DEPLOYMENT_ID", revision);
// Freshのサーバを起動します。
import("./main.ts");
await new Promise((ok) => {
setTimeout(ok, 100);
});
// HTMLを取得するために、FreshのサーバへHTTPリクエストを送信します。
const res = await fetch("http://localhost:8000");
if (!res.ok) {
console.error("Failed to fetch `/`");
Deno.exit(1);
}
// 取得したHTMLを`build`ディレクトリへ出力します。
const html = await res.text();
const buildDir = new URL("./build", import.meta.url).pathname;
await Deno.mkdir(buildDir, { recursive: true });
await Deno.writeTextFile(`${buildDir}/index.html`, html);
Deno.exit(0);
yaml # 省略...
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
if: ${{ github.event_name == 'push' }}
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./build
その他、工夫した点
lint.jsimport { default as awesomeLint } from "npm:awesome-lint@0.18.2";
await awesomeLint.report({ filename: "README.md" });