りゅーそう
元高校地歴科教員。現在microCMSでエンジニアをしています。
Saitama.jsというLT会を運営中です。
発言はすべて個人の意見です。
typescript
blog
2020/02/23
2022/01/23
こんにちは。
みなさん。TypeScript使っていますか?
私は最近ぼちぼち使い始めました。でもまだまだ使いこなせていないなあ〜という感じです。
ただ、使いこなせていない自分でも、もうTypeScriptのない開発には戻れないなあという印象です。
初心者だからこそ、TypeScriptによる開発はメリットが多いです。
コンパイルエラーを教えてくれるので、エラーがでた箇所が特定しやすいなど、初心者だからこそ享受できるメリットも多いはずです。
しかし、なんかTypeScriptというと「型」を覚えたり、「型パズル」なんて言葉があったり、、、とっつきにくい印象がありますよね。
でも、安心してください!
React + TypeScriptで開発を行えば、まずはゆる〜く簡単にTypeScriptを導入することができます!
今回はmicroCMSで作成したAPIに簡単に型をつけるだけ!の簡単〜なTypeScriptをやっていきましょう!
題材として、ありがちなブログサービスを作成していこうと思います。
microCMSのアカウントを持っている。APIの作成方法を知っていることを前提にしています。
知らない方は以下の記事をご覧ください。
note りゅーそうが作成したJamstack tutorial
上記の記事内に引用されている記事もとてもためになるので、読んでおくと理解が深まると思います。
また、当記事ではTypeScriptの入門と書いてありますが、文法・型の詳細な説明はしません。あくまで、TypeScriptを使って見ることを目的としています。TypeScriptの型は以下の記事がとても参考になると思います。
TypeScript 型入門
Next.jsv9~で解説を行います。microCMS + Next.jsの開発はかみむらさん(@kamimura_th)の記事が参考になるので読んでみてください。
Next.js + microCMS + NetlifyでJAMstackな世界に入門する
まずはmicroCMSでAPIを作成します。作成方法は上記の記事を参考に。
今回は以下のようなAPIスキーマを作成してみました。
コンテンツ:
ブログ
※contentの種類は正しくはテキストエリアでした(すいません)。
タグ
今回はこのAPIを前提に話を進めます。
では、フロント側を準備していきましょう。
プロダクトの雛形を作っていきます。
npm init -y
そして、Next.jsに必要なパッケージをインストールしていきます。
npm install next react react-dom
TypeScriptの開発に必要なパッケージのインストール
npm install --save @types/react @types/react-dom @types/node typescript
TypeScriptのコンパイル設定を行うtsconfig.jsonファイルを作成します。
ブラウザではTypeScriptのままでは、コードを読み込むことができません。ブラウザが読み込めるようにJavaScriptに変換して上げる必要があります。
しかし、心配することはありません。Next.jsはTypeScriptのコンパイルを行う機能が備わっているので、tsconfig.jsonを作成することで簡単にコンパイルの設定を行うことができます。
mkdir tsconfig.json
また、
tsc --init
を入力することで、デフォルトの設定込みのファイルを作成することもできます。
Next.jsの公式のexampleを参考に以下のようなファイルを作成しました。
Github zeit/next.js/example
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"lib": ["dom", "ES2017"],
"jsx": "preserve",
"allowJs": true,
"noEmit": true,
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"moduleResolution": "node",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true
},
"exclude": ["node_modules"],
"include": ["src/**/*.ts", "src/**/*.tsx"]
}
設定について詳しくは、公式をご覧ください。
TypeScript Docs
ポイントはstrict:trueの設定を行なっていることです。この設定により、「any」型を厳密にチェックすることができ型を意識した開発を行うことができます。
また、package.jsonのscriptに以下の設定を行います。
"scripts": {
"dev": "next",
"build": "next build",
"export": "yarn run build && next export",
"start": "next start",
"type-check": "tsc --watch"
},
基本的にはyarn dev コマンドを実行し、ブラウザで実行状況をみながら開発を行うと良いでしょう。
実際のアプリケーション開発では、webpackの設定を行なったりする必要があるので導入のハードルは高いですが、Next.jsのSSG開発においては以上で終わりです。このあたりもTypeScriptの導入に適していると思います。
これで、環境は整ったので進めていきましょう。
実際にmicroCMSで作成したAPIに型の情報を与えていきます。
microCMSのAPIリファレンスのページでAPIを試しに叩いてみましょう。(実際にコンテンツをいくつか作成しておいてください。)
こんな感じのレスポンスがあれば成功です。
APIリファレンス < APIを試して見る からcurlコマンドが叩けます。
{
"contents": [
{
"id": "ryusou-blog-start",
"createdAt": "2020-02-15T06:26:10.221Z",
"updatedAt": "2020-02-20T14:13:48.580Z",
"title": "りゅーそうブログを支える技術",
"tags": [
{
"id": "qrpYw36Vr",
"createdAt": "2020-02-12T12:25:02.648Z",
"updatedAt": "2020-02-12T12:25:02.648Z",
"name": "ブログ開発"
}
],
"day": "2020-02-15T07:00:00.242Z",
"image": {
"url": "https://images.microcm....png"
},
"content": "<p>こんにちは。..."
},
{
"id": "ryusou-past-posts",
"createdAt": "2020-02-12T13:43:14.085Z",
"updatedAt": "2020-02-20T14:14:13.281Z",
"title": "りゅーそうの過去の投稿まとめ",
"tags": [
{
"id": "HFQzOpOdm",
"createdAt": "2020-02-12T12:24:13.559Z",
"updatedAt": "2020-02-12T12:24:13.559Z",
"name": "コラム"
}
],
"day": "2020-02-13T12:00:00.000Z",
"image": {
"url": "https://images.microcms-assets.io....png"
},
"content": "<p>りゅーそうの過去のコンテンツの紹介です。....."
},
{
"id": "ryusou-tech-blog-greed",
"createdAt": "2020-02-12T13:11:26.392Z",
"updatedAt": "2020-02-20T14:17:18.422Z",
"title": "ごあいさつ(当ブログについて)",
"tags": [
{
"id": "HFQzOpOdm",
"createdAt": "2020-02-12T12:24:13.559Z",
"updatedAt": "2020-02-12T12:24:13.559Z",
"name": "コラム"
}
],
"day": "2020-02-13T12:00:00.000Z",
"image": {
"url": "https://images.microcms-assets.i.......png"
},
"content": "<p><br><br>こんにちは。......."
],
"totalCount": 3,
"offset": 0,
"limit": 10
}
これをみながら欲しい型の情報を与えるだけです。
Next.jsはsrcディレクトリがサポートされているので、作成しましょう。
mkdir src
type定義のファイルを作成します。
[src/types/index.ts]
export type Post = {
id: string;
title: string;
tags: [
{
id: string;
name: string;
},
];
day?: Date;
image: {
url: string;
};
content: string;
};
先ほどのAPIをみながら、型の情報を与えていくだけです。簡単ですね。(ほとんどstring型...)
dayの横にある?はこの値はなくても大丈夫だよ〜。という意味です(Date型は出力する際にライブラリなどを使って変換して上げる必要があるので、今回はこのような設定にしてあります。)。
これを参照しながら、開発を進めていきます。
Next.jsはpagesディレクトリがそのままルーティングされる仕様になっています。とても便利ですね。例えば、local環境で開発していた場合、src/pages/index.tsxとすると、localhost8000:/ となります。src/pages/aboutとすると、localhost8000:/aboutのようになります。これを利用して、コンテンツを取得するページを作成しましょう。
では、作成したフォルダ内でデータの取得を行なっていきましょう。
APIを叩くためにaxiosをインストールします。axiosはパッケージ内部で型定義がされているので、@typesのインストールは必要ありません。
npm install axios
microCMSのAPIを叩くために、headerにmicroCMSのX-API-KEYを入れます。フォルダを作成して、以下の設定を行います。環境変数はdotenvなどを使用して.envファイルに入力しましょう。
dotenv
[src/lib/api.ts]
import axios from 'axios';
export const axiosInstance = axios.create({
method: 'get',
headers: {
'Content-Type': 'application/json',
'X-API-KEY': process.env.api_key,
},
});
これを利用して、APIを取得します。
[src/pages/index.tsx]
import * as React from 'react';
import { NextPage } from 'next';
import Link from 'next/link';
import { axiosInstance } from '../../lib/api';
import { Post } from '../../types';
type Props = {
posts: Post[];
};
const BlogsPage: NextPage<Props> = ({ posts }) => {
return (
<>
<h2>BLOG 一覧</h2>
<div>
{posts.map(post => (
<React.Fragment key={post.id}>
<Link href={`posts/${post.id}`}>
<a>
<h2>{post.title}</h2>
</a>
</Link>
{post.tags.map(tag => (
<React.Fragment key={tag.id}>
<span>{tag.name}</span>
</React.Fragment>
))}
</React.Fragment>
))}
</div>
</>
);
};
PostsPage.getInitialProps = async () => {
const res = await axiosInstance.get(
`https://ryusou-mtkh.microcms.io/api/v1/posts/`,
);
const data: Post[] = await res.data.contents;
return { posts: data };
};
export default PostPage;
ポイント
こうすることで、gitInitialPropsにまで、型の情報を与えることができます。getinitialPropsにカーソルを当てると、contextにNextPageContentを与えられているのがわかります(※エディタがVSCodeの場合)し、getInitialPropsの中にPromiseの型を与えることができているので、どのような処理をしたら良いのかというのが型の情報から得ることができます。
TypeScriptの型の情報はこのようにドキュメントのように利用することができます。
(getInitialPropsの中ではPromiseの処理を行うんだな〜という感じです。)
この型情報は個別記事取得の際にはさらに役立ちます。
先ほどのコードの中で、
<Link href={`posts/${post.id}`}>
というコードがありましたね。このように[id]の情報をそのままルーティングに当てることができます。Next.js便利ですね。
//[src/pages/[id].tsx] ← このように記述することで、与えられたコンテンツidにページ遷移することができる!
import * as React from 'react';
import { NextPage } from 'next';
import { axiosInstance } from '../../lib/api';
import { IPost } from '../../interfaces';
type Props = {
post: IPost;
};
const PostContent: NextPage<Props> = ({ post }) => {
return (
<>
<h1>{post.title}</h1>
<div>
{post.tags.map(tag => (
<React.Fragment key={tag.id}>
<span>{tag.name}</span>
</React.Fragment>
))}
</div>
<img src={post.image.url} />
<div dangerouslySetInnerHTML={{ __html: `${post.content}` }}></div>
</>
);
};
PostContent.getInitialProps = async context => {
const { id } = context.query;
const res = await axiosInstance.get(
`https://ryusou-mtkh.microcms.io/api/v1/posts/${id}`,
);
const post: Post = await res.data;
return { post };
};
export default PostContent;
基本的には先ほどのコードと一緒ですが、
これで最低限のブログサービスを配信することができました!
このようにWEBサイト制作においても気軽にTypeScriptを導入することができるのが、わかるかと思います。React/Next.jsの学習コストはもちろんありますが、取得できればこのように簡単にサイト作成を行うことができます。
ぜひ、React/Next.jsのシステムを活用して、TypeScriptを気軽にサイト制作にも導入してみてはいかがでしょうか?
また、microCMSはUIもみやすく、取得できるAPIの情報がとてもわかりやすいので、今回のように新しい技術を学ぶ際にやりやすいツールだと思います。
この記事をきっかけにTypeScriptに挑戦してみようかなという方がいらっしゃると嬉しいです!
今回作成したサイトのコードはこちらになります!合わせて参照してください!
GitHub
最後まで読んでくださり、ありがとうございました!