インストール
Remix
npx create-remix@latest
app の種類は Just the basics、deploy 先は Vercel を選びます。
mdx-bundler
npm i mdx-bundler esbuild@0.12.9
esbuild を version 0.12.9 以下でインストールしてください。 Error: The package "esbuild-linux-64" could not be found, and is needed by esbuild.
ファイルを追加
app/content/post.mdx:
---
title: Example Post
published: 2021-02-13
description: This is some description
---
# Wahoo
import Demo from "./demo";
Here's a **neat** demo:
<Demo />
app/util/fs.server.ts:
import fs from "fs/promises";
const CONTENT = `${__dirname}/../app/content`;
export const readContentDir = async () => fs.readdir(CONTENT);
export const readContentFile = async (file: string) =>
fs.readFile(`${CONTENT}/${file}`, "utf-8");
app/util/mdx.server.ts:
export { bundleMDX } from "mdx-bundler";
直接インポートするとクライアントバンドルに入れられてしまうので、専用ファイルを作り除外します。 Error: Could not resolve node:fs
app/routes/index.tsx:
import type { LoaderFunction } from "@remix-run/node";
import { json } from "@remix-run/node";
import { Link, useLoaderData } from "@remix-run/react";
import { readContentDir } from "~/util/fs.server";
export const loader: LoaderFunction = async () => {
const files = await readContentDir();
return json(files);
};
export default function Index() {
const files = useLoaderData();
return (
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.4" }}>
<h1>Welcome to Remix</h1>
<ul>
{files.map((file: string) => (
<li key={file.replace(/\.mdx$/, "")}>
<Link to={"/" + file.replace(/\.mdx$/, "")}>{file}</Link>
</li>
))}
</ul>
</div>
);
}
app/routes/$slug.tsx:
import * as React from "react";
import type { LoaderFunction } from "@remix-run/node";
import { json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
import { getMDXComponent } from "mdx-bundler/client";
import { bundleMDX } from "~/util/mdx.server";
import { readContentFile } from "~/util/fs.server";
export const loader: LoaderFunction = async ({ params }) => {
const post = params.slug;
if (!post) {
throw new Response("Not Found", { status: 404 });
}
const source = await readContentFile(`${post}.mdx`);
const data = await bundleMDX({
source,
files: {
"./demo.tsx": `
import * as React from 'react'
function Demo() {
return <div>Neat demo!</div>
}
export default Demo
`,
},
});
return json(data);
};
export default function Post() {
const { code, frontmatter } = useLoaderData();
const Component = React.useMemo(() => getMDXComponent(code), [code]);
return (
<>
<header>
<h1>{frontmatter.title}</h1>
<p>{frontmatter.description}</p>
</header>
<main>
<Component />
</main>
</>
);
}
remix.config.js:
module.exports = {
serverBuildTarget: "vercel",
server: process.env.NODE_ENV === "development" ? undefined : "./server.js",
ignoredRouteFiles: ["**/.*"],
serverDependenciesToBundle: [
// ここにunified等、使用するESMパッケージを
],
};
コード
リンクは予告なく変更、削除する場合があります。