📕

GistのMarkdownファイルをNext.jsで読み込んで表示する

2020/12/02に公開

プロフィールサイト自作したいね

自分は職務経歴書をgist管理しています。日々の業務でどんなことをやったか、挑戦したかを言語化し、構成図もかなりぼかしてはいるが添えて整理しています。

gistでもきれいに表示してくれるので全く不満はないのですがNext.jsで遊んでみようと思いたち挑戦してみることにしまいた。また今後もgistのマークダウンの方を継続してアップデートしていきたいので、gistのマークダウンを取得してNext.jsで表示してVercelでホストしてみました。

SSRとgetServerSideProps

サーバーサイド・インフラマンなのでフロントのことはあまり分かりませんが、つまりブラウザでAPIやHTTP GETしてレンダリングするのではなく、サーバー側でAPI実行・HTTP GETして、静的なHTMLファイルを返すのがSSRという認識です。

今回gistのマークダウンファイルをVercelのサーバー上で取得して、HTMLを作成する必要があります。それを実現する方法が、getStaticProps or getServerSidePropsになります。それぞれの特徴は以下の通りになります。

  • getStaticProps: デプロイ時にHTTPリクエストを実行してHTMLを作成する
  • getServerSideProps: リクエスト時にHTTPリクエストを実行してHTMLを作成する

gistは非同期で更新されていくのでデプロイ時だと古いgistのままになってしまいます。ということで今回はgetServerSidePropsを使用します。

サンプルコード

import Head from 'next/head';
import Link from 'next/link';
import React, { ReactElement } from 'react';
import ReactMarkdown from 'react-markdown';
import gfm from 'remark-gfm';

const gistResumeUrl = 'https://gist.githubusercontent.com/tMinamiii/f1e93ca728eb66558f19fadb1a9e6feb/raw/resume.md';
type Props = {
  content: string;
};

export async function getServerSideProps(): Promise<any> {
  const resp = await fetch(gistResumeUrl);
  const text = await resp.text();
  console.log(text);
  return { props: { content: text } };
}

const IndexPage: React.FC<Props> = ({ content }: Props): ReactElement => {
  return (
    <div>
      <Head>
        <title>Resume</title>
        <meta charSet="utf-8" />
        <meta name="viewport" content="initial-scale=1.0, width=device-width" />
      </Head>
      <header>
        <nav>
          <Link href="/">
            <a>Home</a>
          </Link>{' '}
        </nav>
      </header>
      <ReactMarkdown plugins={[[gfm, { singleTilde: false }]]}>{content}</ReactMarkdown>
      <footer>
        <hr />
        <span>tMinamiii</span>
      </footer>
    </div>
  );
};
export default IndexPage;

結果

remark-gfmを使ってGitHubライクにしていますが、見た目は本家には遠く及びませんね。。
装飾は今後改良していくとしましょう。このサイトは自分のprofileサイトとして拡充していく予定です。職務経歴書以外にもgistにマークダウンで一旦まとめて、このサイトに公開していく予定です。

https://tminamiii.vercel.app/

Discussion