Markdown BlogをNext.jsで作る

はてなブログに書いてるけど、興味のある技術を試す場としてブログを自分でbuildしようかと思う

Markdownで記事を書くなら、GatsbyJSとかでさくっとできそうだけど、そこはあえて自分が興味あるもので作ってみる

Next.js + MDX + TypeScript でブログを構築していく

Next.js

Installation

$ npm install next react react-dom
$ npm install -D @types/node @types/react typescript

Add Index and Blog page

// src/pages/index.tsx
import Link from 'next/link';

const Index = () => (
  <div>
    <Link href="/blog">
      <a>Blog</a>
    </Link>
  </div>
);

export default Index;
// src/pages/blog.tsx
const Blog = () => (
  <div>
    <p>Welcome to my blog</p>
  </div>
);
export default Blog;

Add npm script

# package.json
{
  ...
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start"
  }
}

Start Next.js

$ npm run dev

これでindexページとblogページが表示できるはず

僕はVSCodeを使ってdebugしたいので ↓ inspect用のスクリプトも用意している

# package.json
{
  ...
  "scripts": {
    "dev": "next",
    "dev:inspect": "NODE_OPTIONS='--inspect=0.0.0.0' next",
    "build": "next build",
    "start": "next start"
  }
}
# .vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Docker: Next.js",
      "skipFiles": [
        "<node_internals>/**"
      ],
      "remoteRoot": "/home/app",
      "protocol": "inspector",
      "port": 9229
    }
  ]
}

MDX

最初は react-markdown + gray-matter で行こうと思ったけど、

MDX が良さそうだったので採用

MDXはMarkdownをJSXで使えちゃうし、導入も楽ちんだった!

Installation

$ npm install @next/mdx @mdx-js/loader
// next.config.js
const withMDX = require("@next/mdx")({
  extension: /\.mdx?$/
});

module.exports = withMDX({
  pageExtensions: ["ts", "tsx", "mdx"]
});
// mdx.d.ts
declare module '*.mdx' {
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  let MDXComponent: (props: any) => JSX.Element;
  export default MDXComponent;
}
# tsconfig.json
{
  ...
  "include": [
    "mdx.d.ts", # 追加
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx"
  ]
}

Add Sample post

// src/posts/sample_post.mdx
export const meta = {
  title: 'Sample Post',
};

# Sample Post

## Welcome to My Blog
// src/pages/blog.tsx
import SamplePost from '../posts/sample_post.mdx';

const Blog = () => (
  <div>
    <SamplePost />
  </div>
);

export default Blog;

参考

f:id:murajun1978:20200210000411p:plain

これでmarkdownの記事を表示することができました{^^)