Typescript、NextJS、Strapi、GraphQLによるブログの作り方
はじめに、使う技術スタックを紹介しましょう。Typescriptは「強く型付けされたプログラミング言語で、任意のスケールでのツーリングを向上させるJavaScriptを拡張します」と言えます。簡単に言うと、Typescriptはコーディングの安全性を高め、ウェブにもっと多くのOOPをもたらします。
NextJSは「最新のReact機能を拡張してフルスタックウェブアプリケーションを作成できるフレームワーク」です。簡単に言うと、NextJSは広く使われているReactJSライブラリのアップグレードです。
StrapiはオープンソースのヘッドレスCMSです。CMSは「コンテンツ管理システム」を意味し、プログラミングの知識がなくても、ユーザーフレンドリーなインターフェースでコンテンツを作成・管理・修正・公開することを可能にします。ヘッドレスとは組み込みのエンドユーザーUIがないことを意味し、好きなフロントエンド技術を使えます。
GraphQLは「APIのためのクエリ言語であり、既存のデータでこれらのクエリを満たすためのランタイム」です。簡単に言うと、それはデータを問い合わせ、欲しいフィールドを取得するために使われる言語です。
注意:これは概要であり、スタイリングや最適なHTMLタグなどいくつかの側面には触れません。このブログは上記の技術を使ってブログを作成する機能を紹介するためのものです。
プロジェクトの初期化
早速コマンドラインを使ってフォルダーを作成しましょう(それがクールだからです)。最初のコマンドは、全てのファイルを含むフォルダを作成することです。
mkdir my-personal-website
それでは、NextJSとStrapiのフォルダを作りましょう。
cd my-personal-website
mkdir frontend, strapi
Strapiの初期化
cd strapi
npx create-strapi-app@latest . --ts --quickstart
パラメータ@latest
は最新バージョンをインストールします。「.」は現在のフォルダにプロジェクトを作成することを意味し、--ts
はTypeScriptを使用することを意味し、最後の--quickstart
はデフォルト設定でインストールされるということです。インストールが終了すると、/admin/auth/register-admin
アドレスの新しいウィンドウが開かれ、新しい管理者アカウントの作成を求められます。進んで新しいアカウントを作成してください。注:この投稿ではソースコードを変更しないので、--ts
を使うのはオプションです。
NextJSの初期化
cd frontend
npx create-next-app@latest . --ts
最後に、Githubリポジトリを初期化することを忘れないでくださいが、この投稿ではカバーしません。
Strapiの開始
私はプロジェクトでバックエンドから始めるのが好きなので、バックエンドと見なされるStrapiから始めましょう。
GraphQLのインストール
Strapiの利点の一つは、GraphQLとの簡単な統合です。GraphQLプラグインをインストールするには、次のコマンドを実行する必要があります。
npm run strapi install graphql
_Duplicate "graphql" modules_
エラーが出たら心配しないでください。対処法は簡単です;全てが必要なのはnode_modulesフォルダとpackage-lock.jsonを削除し、パッケージを再インストールすることです。
rm -rf node_modules
rm package-lock.json
npm install
npm run strapi dev
インストールに成功したら、/graphql
のURLを訪れることができます。
ブログ投稿コレクションの作成
Strapiのホームページをhttp://localhost:1337/admin/
で開き、サインインしたら、コンテンツタイプビルダーページに行き、新規コレクションタイプ作成ボタンをクリックし、表示名フィールドに適切な名前を入力します。私はブログ投稿を選びます。その後、続けてください。
新しいコレクションのフィールド選択に入るところです。好きなようにカスタマイズできますが、簡単にするために、タイトル用のテキストフィールド、説明用のもう一つのテキストフィールド、最後に本文用のリッチテキストフィールドを追加します。次に保存をクリックします。
コレクションを持つことができたら、データでそれを入力する必要があります。コンテンツマネージャーに行き、新しく作成されたコレクションが見えるはずです。それをクリックして、新しいエントリを作成ボタンをクリックして、好きなデータを入力し、保存して公開しましょう。
アクセス権限オプション1:公開アクセス可能
データにGraphQLを使ってアクセスできるようにする前に、アクセス可能にする必要があります。公開アクセス可能にすることもできますし、認証済みユーザーのみにすることもできます。私は機密データを保存していないので、公開アクセス可能なコレクションを選びます。
公開アクセス可能にするには、設定に行き、ロールをクリックし、パブリックをクリックし、作成したコレクションをスクロールして見つけ出します(私の場合はブログ投稿です)、それをクリックし、findとfindOneにチェックを入れます。
アクセス権限オプション2:認証済みのみ
しかし認証済みの方法を選ぶ場合は、こうしてください。これを実現する方法は2つあります;1つ目は、設定ページでAPIトークンを作成し、リクエストに添付する必要があります。それをヘッダーにAuthorizationヘッダーとして追加して、値をbearerに設定します。2つ目の方法は、コンテンツマネージャーページを通じてユーザーコレクションに新しいエントリを作成し、その新しく作成したユーザーのユーザー名またはメールアドレスとパスワードを含むJSONボディを添えて/api/auth/local
にポストリクエストを送ることです。ストラッピーを初期化する際に作成した管理者アカウントではありません。
{
"identifier": "email or username",
"password": "password"
}
リクエストが成功したら、JWTフィールドを含む返事を受け取ります。次に、リクエストごとに同じことをして、ヘッダー内に送信し、Authorizationヘッダーの値をbearerと設定します。
アクセスするには、設定に行き、ロールをクリックし、認証済みをクリックします。作成したコレクションをスクロールして見つけ出します(私の場合はブログ投稿です)、それをクリックし、findとfindOneにチェックを入れます。
GraphQLエンドポイントのテスト
GraphQLにアクセスするには/graphql
を訪れます。そして、左側の入力フィールドにクエリを入力してStrapiアプリケーションを問い合わせることができます。クエリの例:
query {
blogPosts {
data {
id
attributes {
title
description
body
}
}
}
}
私の場合の返事は:
"data": {
"blogPosts": {
"data": [
{
"id": "1",
"attributes": {
"title": "test",
"description": "test",
"body": "test"
}
}
]
}
}
}
RESTエンドポイントのテスト
することは/api/blog-posts/
にGETリクエストを送ることだけです。返事の例は:
{
"data": [
{
"id": 1,
"attributes": {
"title": "test",
"description": "test",
"body": "test",
"createdAt": "2023-01-30T20:28:28.141Z",
"updatedAt": "2023-01-30T20:28:29.027Z",
"publishedAt": "2023-01-30T20:28:29.025Z"
}
}
],
"meta": {
"pagination": {
"page": 1,
"pageSize": 25,
"pageCount": 1,
"total": 1
}
}
}
Strapiセクションはこれで終わりで、NextJSを続けます。
NextJSの開始
**pages**ディレクトリ内に新しいディレクトリを作成し、blog
と名付けます。次に、新しいindex.tsx
ファイルを作成し、基本的なreactコンポーネントを初期化します。
import {NextPage} from "next";
interface Props {
}
const About: NextPage<Props> = (Props) => {
return (
<p>About Page</p>
)
}
export default About;
これでblog
を訪れてAboutページが見れます。
インターフェイスの作成
何個かのインターフェイスが必要になります。始めるにあたって、基本的なモジュールを含む**commonフォルダを新たに作成し、次に全てのタイプとインターフェイスを含むtypesフォルダを作成しましょう。そして新たなtypescriptを作成し、BlogInterfaces**と命名します。最初のインターフェイスはIBlogIdentification
で、私たちの識別フィールド、つまりブログ投稿のidを含むものになります。
export interface IBlogIdentification {
id: string
}
次に、ブログのフィールドのタイトル、説明、本文を含むインターフェイスが必要です。それをIBlogFields
と名付けます。
export interface IBlogFields {
title: string,
description: string,
body: string
}
次に、GraphQLクエリから受け取るブログ属性のインターフェイスが必要です。それをIBlogAttributes
と名付けましょう。
export interface IBlogAttributes {
attributes: Partial<IBlogFields> & Pick<IBlogFields, 'title'>
}
私はIBlogFields
の全てのフィールドをオプショナル(任意)にするためにPartial型とPick型を使用しました。ただしタイトルは除く。
最後に、ブログエントリ全体を扱うためのインターフェイスが必要です;それをIBlog
と名付けましょう。
export interface IBlog extends IBlogIdentification, IBlogAttributes{}
**blog**ページのPropsインターフェイスを更新しましょう。
interface Props {
blogs: IBlog[]
}
GraphQLワークス
データのフェッチを開始する前に、GraphQLワークスが必要になります。まず2つのパッケージ、graphql
と@apollo/client
パッケージをインストールする必要があります。
npm i graphql @apollo/client
次に、クエリを書く必要があります。ブログをリストするための最初のクエリ、二つ目は単独のブログを取得するためのクエリ、そして最後はブログIDのリストを取得するためのクエリです。**common**フォルダ内に新しいフォルダを作成しgraphql
と名付け、新しいファイルを作成しqueries.tsx
と名付け、次のクエリを追加しましょう。
export const LIST_BLOG = gql(`query {
blogPosts {
data {
id
attributes {
title
}
}
}
}`)
export const SINGLE_BLOG = gql(`query ($blogId: string!) {
blogPosts(filters: {id: {eq: $blogId}}) {
data {
id
attributes {
title
description
body
}
}
}
}`)
export const LIST_ID = gql(`query {
blogPosts {
data {
id
}
}
}`)
必要な次のことは、Strapiのアドレスを保存することです。最も便利な方法は環境変数の中に保存することです。NextJSには既に組み込みの環境変数モジュールがあるので、dotenv
をインストールする必要はありません。やるべきことはnext-config.js
に行って、次のエクスポートを追加することです。
module.exports = {
env: {
STRAPI_ADDRESS: "http://127.0.0.1:1337/graphql"
},
nextConfig,
}
最後に必要なことは、GraphQLサーバーに接続するためのApolloClient
です。**graphql**フォルダ内に新しいファイルを作成し、client.tsx
と名付け、次のコードを追加します。
import {ApolloClient, InMemoryCache, NormalizedCacheObject} from "@apollo/client";
const client: ApolloClient<NormalizedCacheObject> = new ApolloClient({
uri: process.env.STRAPI_ADDRESS,
cache: new InMemoryCache(),
});
export default client;
注意:キャッシュはApolloClient
が結果をキャッシュ
こちらの記事はdev.toの良い記事を日本人向けに翻訳しています。
https://dev.to/kadiemq/typescript-nextjs-strapi-and-graphql-an-overview-of-how-i-created-my-blog-61g