Kain's blog
Next.jsでブログを作った
Created: 2021-3-11 1:57:50
(Last updated: 2021-3-12 2:14:48)
Next.jsとtailwindcssとContentfulとVercelでブログを作ったというタイトルそのまんまの話です。
Next.jsのインストールなど
諸事情でcreate-next-appが使えなかったので npm initしてからNext.jsのインストールをしました。
自分は型付けがないと生きていけない性なので、TypeScriptとその型定義もついでにインストールします。インストール後にtsconfig.jsonを作っておくとNextの初回起動時にtsconfigの中身を埋めてくれるので空のファイルをとりあえず作る。ついでにtailwindcssやESLint、prettierなどをインストールしておく。
> npm i next react react-dom
... (中略)
> npm i -D @types/react @types/react-dom @types/node typescript next-compose-plugins
... (中略)
> touch tsconfig.json
> npm i tailwindcss
... (中略)
> npm i -D postcss autoprefixer
... (中略)
ディレクトリ構造はこんな感じにしました
.
├── .editorconfig
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .prettierrc
├── next-env.d.ts
├── package-lock.json
├── package.json
├── postcss.config.js
├── public
├── src
│ ├── components
│ ├── lib
│ └── pages
├── tailwind.config.js
└── tsconfig.json- .editorconfig, .eslintignore, .gitignore
- 略
- package-lock.json, next-env.d.ts
- 略その2
- .eslintrc.js
- ESLintの設定ファイル。settingsのreactのversionを設定しないと微妙にwarn入ったりする。
- eslint-config-prettier使おうね
- package.json
- これは余談なんですがgit管理下で
npm initするとrepositoryだったりbugsだったり埋めてくれるんですね
- これは余談なんですがgit管理下で
- postcss.config.js, tailwind.config.js
- tailwindcssの公式にあるように
npx tailwindcss init -pして自動生成されたファイルにpurgeを加えたのみ。 - 注意事項はディレクトリ構成を変更しているのでsrc直下をpurgeするようにする。
- tailwindcssの公式にあるように
- public
- 画像とか置く場所です
- src/components
- Layout.tsxとかその他もろもろのコンポーネントを置く場所
- src/lib
- 後述するcontentfulからデータを取ってくる用
- src/pages
- ページそのもの
- getStaticPropsとかgetStaticPathsとか使いました
- tsconfig.json
- TypeScript用
- Nextが自動生成するのだとstrict: falseになってたりするのでこれは修正する
Contentfulの設定など
アカウントを取得してContent modelに適当なブログのモデルを作成してフィールドを追加する。 このブログでは、title, body, slug, imagesを追加しました。(images使い方わかりませんが) bodyはRich TextではなくTextとから選ばないとMarkdown形式での入力ができない点は微妙に躓いた。
次に、npm i contentfulしてcontentfulで書いた記事をNext側から読み込む部分を作成した。
// lib/api.ts
import { createClient } from 'contentful';
const client = createClient({
space: '***',
accessToken: '*****',
});
interface Entry {
body: string;
title: string;
slug: string;
createdAt: string;
updatedAt: string;
beforeSlug?: string;
afterSlug?: string;
}
let entries: Entry[] | undefined = undefined;
export const getPaths = async (): Promise<string[]> => {
const entries = await client.getEntries<Entry>();
const items: string[] = [];
for (const item of entries.items) {
items.push(item.fields.slug);
}
return items;
};
export const getEntries = async (): Promise<Entry[]> => {
if (entries) {
return entries;
} else {
const currentEntries = await client.getEntries<Entry>();
entries = currentEntries.items.map((x) => ({
...x.fields,
createdAt: x.sys.createdAt,
updatedAt: x.sys.updatedAt,
}));
for (let i = 0; i < entries.length; i++) {
const element = entries[i];
if (i != 0) {
element.beforeSlug = entries[i - 1].slug;
}
if (i != entries.length - 1) {
element.afterSlug = entries[i + 1].slug;
}
}
return entries;
}
};
spaceとaccessTokenはContenful > Settings > API Keyから取得できるのでそれを使った。
getStaticPropsとか
すごく簡単にできて便利ですね。 注意点としてはslugとかは絶対パスで書かないとエラーが生じる。
その他
アイコンとか
アイコンに@material-ui/iconsを使ったんですが、これは単体だとデプロイできなくて@material-ui/coreもインストールする必要がある。
tailwindcssとか
CSSなんもわからんけどこれなら割と使える気がする。
ところでnext dev時にDevToolsでスタイル弄ってると重くなるのはどうしようもないんですか?
Vercelへのデプロイ
Githubからimportするだけで終わったですが、なにも書くことがない。
感想
コードハイライト入れたら露骨にLighthouseのスコア落ちたんですがこれどうにかならないんですか
ビルド時にコードハイライトもマークダウンへの変換も行うようにしたら無事解決しました