X

Hi, thank you for visiting here. Have a nice day. 👋

S

React/Next.js, Contentful, Material-UIを使ってブログを作り、Vercelで公開します。

ReactのフレームワークNext.js、Headless CMSにContentful、Material-UIを使ってブログを作っていきます。GitHubからコードをクローンしてすぐにブログを作れます。
Satoru Akiyama
ProgramingJapanese
React/Next.js, Contentful, Material-UIを使ってブログを作り、Vercelで公開します。 photo
BlogSeptember 19, 2020

完成するブログ🤩

この記事ではこちらのブログアプリを作っていきます。見ていただければわかりますが、とてもサクサク動く爆速なブログになっています。PCでもスマホでも綺麗なデザインになっています。

この記事では、こちらのコードを使ってブログを作っていきます。自分で一から作りたい場合は、Vercelが出しているドキュメンテーションGitHubのコードのコードが参考になると思います(私はこの二つを見ながら今回紹介するブログを作りました)。

必要な知識、前提条件🙏

  • React/Next.jsの基礎知識(基礎だけで十分です)
  • Node.js、Gitをインストール済み
  • GitとGitHubの基本的な使い方(GitHubのアカウントを持っていて、add, commit, push,cloneなどを知っていれば十分です)
  • Headless CMSとは何か

技術スタック 🔷

1. Next.js

フロントエンドには、ReactのフレームワークであるNext.jsを使います。

2. Contentful

Contentfulは、Headless CMSの一つです。とても有名で、速くてフレキシブルなCMSです。

3. Material-UI

今回作るブログアプリのスタイリングには、ReactのUIフレームワークで有名なMaterial-UIを使います。


それでは、作っていきましょう!💫

Step1から11まであります。長い記事になっていますが、最後まで読んでいただけると嬉しいです。*この記事の情報は2020/09/18のものです。


Step1 Contentfulのアカウントを作る

まずはContentfulのアカウント登録をして下さい。GitHubアカウント、Googleアカウント、または、メールアドレスで登録できます。


Step2 Contentfulのコンテンツを作る

アカウントを登録したらまず、新しくSpaceを作って下さい。「Space Name」は何でも良いです。そして、ヘッダータブから「Content model」に行ってください。そして「Add content type」ボタンを押して下さい。Content Typeを作るのですが、間違うとエラーの原因になるので、誤字脱字に気を付けてください。

「Name」、「Api Identifier」ともに、「author」と設定し、「Create」を押してください。そしたら、「Add field」ボタンを押し以下2つのfieldを追加してください。

  • Short text Name: Name, Field ID: name
  • Media Name: image, Field ID: image

もう一つコンテンツタイプを作ります。「Add content type」ボタンを押して下さい。「Name」、「Api Identifier」ともに、「post」と設定し、「Create」を押してください。そしたら、「Add field」ボタンを押し以下7つのfieldを追加してください。

  • Short text Name: title, Field ID: title
  • Short text Name: sub title, Field ID: subTitle
  • Short text Name: slug, Field ID: slug
  • Date & time Name: date, Field ID: date
  • Reference Name: author, Field ID: author
  • Media Name: coverImage, Field ID: coverImage
  • Rich text Name: content, Field ID: content

これで「Content Model」の設定は終了です。それでは、ヘッダータブから「Content」 タブを押してください。「Content type」を「author」 にして「Add author」 ボタンを押し、「author」を追加してください。同じように、今度は「post」を追加してください。1つでも2つでもかまいません。ここで「Contentful自体」の設定は終わりです。

Step3 GituHubからコードをクローン

今回は私が作ったコードをスターターとして使います。今回のプロジェクトに使うフォルダを作成して、コマンドに

git clone https://github.com/SatoruAkiyama/blog-with-nextjs-and-contentful.git

を貼り付けて、Enter keyを押してください。クローンが終わると「blog-with-nextjs-and-contentful」というファイルがあるので、そのファイルをコーディングエディターを開いて下さい。


Step4 Space IDとContent Delivery API - access token

Contentfulからデータを取得するために、Space IDとContent Delivery API - access token を設定します。そのために、プロジェクトディレクトリ直下に「.env.local」というファイルを作ってください。そして、ヘッダータブから「Setting」→「API keys」と進んでください。すでにデフォルトのモノがあると思うので、それを選択するか、右側の「+Add API Key」から新しいキーを作ってもいいです。

そしたら、Space IDとContent Delivery API - access tokenを以下のように/.env.localにコピペして保存して下さい。

NEXT_PUBLIC_CONTENTFUL_SPACE_ID=あなたのSpace ID
NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN=あなたのContent Delivery API - access token


これで、ブログの準備が出来ました。npm install してください。終わったら、npm run devをして、http://localhost:3000/を開いてください。

Step5 Contentfulからのデータ取得

/lib/index.jsにContentfulからのデータ取得するための関数を全て定義しています。

// lib/index.js


const client = require("contentful").createClient({
  space: process.env.NEXT_PUBLIC_CONTENTFUL_SPACE_ID,
  accessToken: process.env.NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN,
});

// 全てのpostを取得
export async function getAllPosts() {
  const entries = await client.getEntries({
    
    // Content typeがpostのデータだけ取得
    content_type: "post",
    
    // postが作られた時間順に取得
    order: "-fields.date",
  });
  if (entries.items) {
    return entries.items;
  }
  console.log(`Error getting Entries for ${contentType.name}.`);
}

// URLごとにpostを取得
export async function getPostBySlug(slug) {
  const entries = await client.getEntries({
    content_type: "post",
    
    // 取得データの数
    limit: 1,
    
    // slugの値が引数slugと等しいpostを取得
    "fields.slug[in]": slug,
  });
  if (entries.items) {
    return entries.items[0];
  }
  console.log(`Error getting Entries for ${contentType.name}.`);
}

// 最新のpostsを3つ取得
export async function getMorePosts(slug) {
  const entries = await client.getEntries({
    content_type: "post",
    limit: 3,
    order: "-fields.date",
    
     // slugの値が引数slugと等しくないpost
    "fields.slug[nin]": slug,
  });

  if (entries.items) {
    return entries.items;
  }
  console.log(`Error getting Entries for ${contentType.name}.`);
}

function parsePostSlug({ fields }) {
  return {
    slug: fields.slug,
  };
}

function parsePostSlugEntries(entries, cb = parsePostSlug) {
  return entries?.items?.map(cb);
}

// 全てのpostのURLを取得
export async function getAllPostsWithSlug() {
  const entries = await client.getEntries({
    content_type: "post",
    
    // postのslugの値を取得
    select: "fields.slug",
  });
  return parsePostSlugEntries(entries, (post) => post.fields);
}

詳しく知りたい方はContentfulの公式ドキュメンテーションを読んでください。これらの関数を、/pages/index.js/pages/blog/[slug].js内で呼び出しています。呼び出す際にはgetStaticProps()getStaticPaths()という関数内で呼び出します。この関数について分からない場合は、Next.jsの公式ドキュメンテーションを読んでください。

Step6 ソーシャルメディア

ソーシャルメディアのURLをあなたのものにしましょう。

/data/socialMedia.jsを開いて下さい。デフォルトでは、Instagram, Facebook, GitHub, HomepageのURLがそれぞれ設定されているので、自分のURLに設定しなおして下さい。追加、削除も可能です。

// socialMedai.js


// 自分のURLに変えてください
export const socialMedia = {
  instagram: "https://www.instagram.com/developer_satoru_akiyama/",
  facebook: "https://www.facebook.com/satoruakiyama1998",
  github: "https://github.com/SatoruAkiyama/blog-with-nextjs-and-contentful",
  homepage: "https://satoruakiyama.com",
  // 追加したい場合は下記のように追加してください。
  // twitter: "https://twitter.com", 
};

変更した場合は、/components/Social.jsを開いて、コードを修正してください。Material-iconに関しては、こちらからどのようなものか確認ください。

// Social.js


// 例 Twitter を追加した場合、下記を追加して下さい

// 8行目に追加
import TwitterIcon from '@material-ui/icons/Twitter';

// 32行目を変更。(twitterを足すだけです。)
const { instagram, facebook, github, homepage, twitter } = socialMedia;

// そして98行目の下に以下のコードをペーストして下さい。
<Grid
  item
  component={"a"}
  target="_blank"
  rel="noreferrer noopener"
  href={twitter}
>
  <TwitterIcon className={classes.snsIcon} />
</Grid>

すると、FooterのアイコンとAboutページのアイコンにTwitterアイコンが追加されていると思います。

Step7 About ページ

/pages/aboutを開いてください。名前、写真、自己紹介文を編集します。

// about.js


// 31行目を変更
const name = "あなたの名前"

// 33行目を変更
const avatar = "あなたの写真"

// 71行目の下のテキストをあなたの自己紹介にして下さい。

Step8 metaタグ、ページタイトル

最後に<title><meta name="description" content=""/>の設定をしましょう。このブログアプリでは、<head>タグ</head>の値は/components/layout/Layout.js にプロップスとして渡しています。/pages/index.js/pages/about.jsを開いてください。ページのタイトルとページの説明を変更してください。

// index.js


// 19行目 <title>の値
title="ページのタイトル"

// 20行目 <meta name="description" content=""/> のcontentの値
description="ページの説明"
// about.js


// 38行目 <title>の値
title="ページのタイトル"

// 39行目 <meta name="description" content=""/> のcontentの値
description="ページの説明"

Step9 ホームページヘッダー

この部分を編集しましょう。/components/PageHeader.jsを開いてください。自由に変更する又は、削除してください。削除する場合は、/pages/index.jsを開いて、PageHeaderコンポーネントを使っているコードを削除してください。

Step10 デプロイ

最後に作ったブログをVercelにデプロイしましょう。まずはGitHubで今回作ったブログをコミットするために、レポジトリ―を作ってください。コマンドにgit remote set-url origin あなたのレポジトリーのURLを貼り付けてEnter keyを押して下さい。そして、git add. , git commit, git push を行ってください。そしたら、VercelのアカウントをGithubと連携してこちらから作ってください。プロジェクトをGitHubからImport します。

Continueを押すと、GitHubのURLを聞かれるので、先程作ったレポジトリーのURLを入力してください。すると以下の画面になると思います。

ここでDeployを押す前に、Enviroment Variables を設定します。設定するものは、「Space ID」と「Content Delivery API - access token」です。

NAMEに「NEXT_PUBLIC_CONTENTFUL_SPACE_ID」 、 VALUEに、「あなたのSpace ID」 を入力して、Addを押してください。そして次に、NAMEに「NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN」、VALUEに、あなたの「Content Delivery API - access token」を入力して、Addを押してください。この2つのEnviroment Variables を設定できたら、Deployを押してください。Deployが終わると、サイトが公開されています。お疲れさまでした!


Step11 カスタマイズ

もし、ページを増やしたい(例えばコンタクトページなど)場合は、/data/routes.jsを開いて、routesの配列に加えてください。そうすると、Nav MenuとFooterにlinkが加えられます。そのあとにpageフォルダにそのページを作って下さい。デザインを変えたい場合は、Material-UIのドキュメンテーションを参考にしてください。

終わりに😎

最後まで読んで頂きありがとうございました。感想、分かりづらい点や、バグなどがございましたら、ご連絡いただけると嬉しいです。またこの記事を参考にして、作った制作物などのURLを送って頂けると、この記事を書いて良かったと思えるのでありがたいです。

追記(2023/11/23)

verceにデプロイする時にエラーが出てしまう場合、下記を試してみてください。

  • dashboardでプロジェクトを選択
    ・Settingsタブに移動
  • General->Build & Development Settingsの「install command」に「npm install: --legacy-peer-deps」を設定
  • Environment VariablesにKey: NODE_OPTIONS、value: --openssl-legacy-providerを追加

Share

この記事が役に立てば是非シェアして下さい!

ブログの記事を読んで頂きありがとうございます。何か気になる事やご相談などございましたら、お気軽にご連絡ください!

avatat Satoru Akiyama

他の日本語の記事

| All Posts | English | Japanese |