- チュートリアル
- フレームワーク
NewtとNuxt3を利用してブログを作成する
このチュートリアルでは、Newtと Nuxt3 を利用して、ブログを作成する手順を紹介します。
具体的には、Newtで管理しているコンテンツの一覧ページと詳細ページを作る手順を紹介します。
記事内で使用している主なソフトウェアのバージョン
- Nuxt(
nuxt
): 3.2.0 - newt-client-js(
newt-client-js
): 3.2.4
概要
Nuxt3でプロジェクトを作成し、Newtのコンテンツ情報を取得できるようにします。
コンテンツの一覧ページ(パス: /
)と詳細ページ(パス: /articles/:slug
。slugがarticle-1の場合は /articles/article-1
)を作成し、ローカル環境で表示を行うまでを説明します。
また、ここでは(クライアントサイドレンダリングではなく)ユニバーサルレンダリングを利用し、かつプリレンダリングを行う方法を紹介します。これはビルド時に静的にHTMLを生成する方法となります。
1. Nuxt3のセットアップ
1-1. プロジェクトの作成
はじめに、Nuxt3のセットアップを行います。以下のコマンドでプロジェクトを作成します。
<project-name>
には好きな名前を入力しましょう。
npx nuxi init <project-name>
ここでは nuxt3-blog
という名前で作成します。
npx nuxi init nuxt3-blog
作成したプロジェクトに移動して、依存関係をインストールした後、開発サーバーを立ち上げます。yarnを利用する場合は以下のようになります。
$ cd nuxt3-blog
$ yarn install
$ yarn dev
http://localhost:3000
にアクセスして、以下のような画面が表示されることを確認します。
1-2. TypeScriptの設定
開発環境でも型のチェックを行うために、以下の設定を行います。
※ 開発環境で型のチェックを行わない場合は、1-2のステップを飛ばして構いません。
まず @types/node
・vue-tsc
・typescript
をdevDependenciesとしてインストールします。
yarn add -D @types/node vue-tsc typescript
さらに、nuxt.config.ts
ファイルで typescript.typeCheck
オプションを有効にします。
export default defineNuxtConfig({
typescript: {
typeCheck: true
}
})
これで開発環境でも型のチェックができるようになりました。
TypeScriptの設定について、詳細はNuxtの TypeScript のドキュメントをご確認ください。
2. Newtのセットアップ
次にNewtにコンテンツとAPIトークンを用意し、コンテンツの取得を行うための準備を行います。
2-1. Appを追加する
「Appを追加」をクリックして「テンプレートから追加」を選択します。
表示されるテンプレートの中から「Blog」を選択して、「このテンプレートを追加」をクリックします。
テンプレートが追加されると、「投稿データ」「カテゴリデータ」「著者データ」が追加されます。
2-2. スペースUID・App UID・モデルUIDを確認する
スペースUIDは「スペース設定」から確認できます。
上記の例だと、スペースUIDは sample-for-docs
となります。
この値は3-1で環境変数として定義します。
また「Blog」テンプレートを追加した場合、App UIDは blog
、「投稿データ」モデルUIDは article
となります。
これらの値は、4-4や5-1で投稿情報を取得する際に利用します。
2-3. Newt CDN API Tokenを作成する
続いて、APIリクエストに必要なトークンを発行します。
スペース設定 > APIキー のページからNewt CDN API Tokenを作成します。
名前と取得対象を決めて「作成」を押します。
ここで作成したトークンの値は3-1で環境変数として定義します。
3. リクエストの準備
Newtの SDK を利用することで、NewtのAPIをより簡単に利用できます。
ここではSDKを利用して、NewtのAPIクライアントを作成します。
3-1. 環境変数の設定
Nuxtの Runtime Config を利用して、環境変数を利用できるようにします。
まず、.env
ファイルを作成し、2-2で確認したスペースUID、2-3で作成したトークンの値を定義します。以下を、実際の値で置き換えて定義してください。
NUXT_NEWT_SPACE_UID=sample-for-docs
NUXT_NEWT_CDN_API_TOKEN=xxxxxxxxxxxxxxx
あわせて、nuxt.config.ts
に以下のように runtimeConfig
の設定を追加します。
export default defineNuxtConfig({
+ runtimeConfig: {
+ newt: {
+ spaceUid: '',
+ cdnApiToken: ''
+ }
+ },
typescript: {
typeCheck: true
}
})
Runtime Confingは実行時にマッチする環境変数に自動的に置き換えられるため、上記のように定義しておくと、runtimeConfig.newt.spaceUid
の値は .env
ファイルの NUXT_NEWT_SPACE_UID
の値に置き換えられ、runtimeConfig.newt.cdnApiToken
の値は .env
ファイルの NUXT_NEWT_CDN_API_TOKEN
の値に置き換えられます。
また、これらの変数はサーバーサイドでのみ参照できる、プライベートな変数となります。
Runtime Configの詳細については、Nuxtの Runtime Config のドキュメントをご確認ください。
3-2. newt-client-jsのインストール
次に newt-client-js をインストールします。
npm install newt-client-js
# or
yarn add newt-client-js
3-3. プラグインの作成
プラグインを作成し、CDN APIを利用するためのクライアントを定義します。
プラグインはNuxtアプリケーションの初期化時に実行されます。デフォルトではサーバーサイド、クライアントサイド双方で実行されます。
Nuxtは plugins
ディレクトリにあるファイルを自動的に読み込んで、Vueアプリケーションの作成時にロードします。ファイル名に .server
または .client
というサフィックスを付けると、サーバー側またはクライアント側でのみプラグインを読み込むことができます。
ここではサーバーサイドでのみ読み込めれば良いので、plugins
ディレクトリを作成し、その中に newt.server.ts
というファイルを作成します。
// plugins/newt.server.ts
import { createClient } from 'newt-client-js'
export default defineNuxtPlugin(() => {
const config = useRuntimeConfig()
const newtClient = createClient({
spaceUid: config.newt.spaceUid,
token: config.newt.cdnApiToken,
apiType: 'cdn'
})
return {
provide: {
newtClient
}
}
})
これで、Vueコンポーネント内から、Newtのクライアントを利用できるようになりました。
プラグインの詳細については、Nuxtの Plugins Directory のドキュメントをご確認ください。
4. 一覧ページの作成
4-1. 言語の設定をする
nuxt.config.ts
で lang 属性を設定します。ここでは日本語 ja
を指定します。
export default defineNuxtConfig({
+ app: {
+ head: {
+ htmlAttrs: {
+ lang: 'ja'
+ }
+ }
+ },
runtimeConfig: {
newt: {
spaceUid: '',
cdnApiToken: ''
}
},
typescript: {
shim: false,
typeCheck: true
}
})
4-2. 投稿の型を定義する
投稿の型 Article
を定義しておきます。
このチュートリアルでは、_id
・title
・slug
・body
のみを使うため、以下のように定義しておきます。
// types/article.ts
export interface Article {
_id: string
title: string
slug: string
body: string
}
4-3. NuxtPageを設定する
この後に作成する pages
ディレクトリ配下のページを表示できるように、app.vue
ファイルを修正します。NuxtWelcome
を NuxtPage に変更します。
<template>
<div>
- <NuxtWelcome />
+ <NuxtPage />
</div>
</template>
4-4. 投稿一覧を取得する
Nuxtではファイルシステムベースのルーティングを採用しており、pages
ディレクトリの配下にファイルを作成すると、自動的にルートとして利用できるようになります。
例えば、以下のようにルーティングされます。
pages/blog/index.vue
→/blog
pages/blog/first-post.vue
→/blog/first-post
※ ルーティングの詳細については、Nuxtの Routing のドキュメントをご確認ください。
ここではトップページ(パス: /
)で投稿一覧を表示したいので、pages
ディレクトリを作成し、その中に index.vue
というファイルを作成します。
まず、script
タグに以下の内容を記載します。
useAsyncData を利用してNewtから投稿一覧を取得し、articles
という変数で定義することで、template
の中で参照できるようにしています。
また、useHead を利用して、タイトルとディスクリプションを設定しています。
<!-- pages/index.vue -->
<script lang="ts" setup>
import type { Article } from '~/types/article'
const { data } = await useAsyncData('articles', async () => {
const { $newtClient } = useNuxtApp()
return await $newtClient.getContents<Article>({
appUid: 'blog',
modelUid: 'article',
query: {
select: ['_id', 'title', 'slug', 'body']
}
})
})
const articles = data.value?.items
useHead({
title: 'Newt・Nuxtブログ',
meta: [
{ name: 'description', content: 'NewtとNuxtを利用したブログです' }
]
})
</script>
データの取得について詳細を説明します。
まず、useNuxtApp を利用して、3-3で登録した newtClient
を利用できるようにします。
次に、SDKが提供している getContents メソッドを利用して、投稿一覧を取得します。getContentsのパラメータに Article
の型を渡すことで、返却される items
の型として Article[]
が指定されます。
また、selectパラメータを利用して、取得するフィールドを _id
・title
・slug
・body
のみに制限します。
最後に articles
として data.value?.items
を定義することで、getContentsで返却されたオブジェクトの items
要素を articles
として参照できるようにします。
4-5. 投稿一覧を表示する
4-4で定義した articles
を利用して、template内で投稿一覧を表示できるようにします。
pages/index.vue
に以下の部分を追加します。
<template>
<div>
<ul>
<li v-for="article in articles" :key="article._id">
<NuxtLink :to="`/articles/${article.slug}`">
{{ article.title }}
</NuxtLink>
</li>
</ul>
</div>
</template>
http://localhost:3000/
にアクセスして、以下のように投稿一覧が表示されれば成功です。
5. 詳細ページの作成
5-1. 投稿詳細を取得する
Nuxtでは [param]
のようにしてページ名に角括弧を使うことで動的なルーティング(Dynamic Routes)を作成できます。ここでは、/articles/:slug
(/articles/article-1
など)のパスで投稿の詳細を表示したいので、pages/articles/[slug].vue
のファイルを作成します。
まず、script
タグに以下の内容を記載します。
投稿一覧の取得と同様に、useAsyncData を利用します。article
という変数で定義することで、template
の中で参照できるようにしています。
<!-- pages/articles/[slug].vue -->
<script lang="ts" setup>
import type { Article } from '~/types/article'
const route = useRoute()
const { slug } = route.params
const { data } = await useAsyncData(`article-${slug}`, async () => {
const { $newtClient } = useNuxtApp()
return await $newtClient.getFirstContent<Article>({
appUid: 'blog',
modelUid: 'article',
query: {
slug,
select: ['_id', 'title', 'slug', 'body']
}
})
})
const article = data.value
useHead({
title: article?.title,
meta: [
{ name: 'description', content: '投稿詳細ページです' }
]
})
</script>
投稿詳細を取得するメソッドとして、SDKが提供している getFirstContent を利用しています。このメソッドはクエリに該当するコンテンツのうち、最初の1件を返却するメソッドです。指定したスラッグのコンテンツを取得したい場合は、このメソッドを利用します。
5-2. 投稿詳細を表示する
5-1で定義した article
を利用して、template内で投稿詳細を表示できるようにします。
pages/articles/[slug].vue
に以下の部分を追加します。
<template>
<main class="main">
<h2>{{ article?.title }}</h2>
<!-- eslint-disable-next-line vue/no-v-html -->
<div v-html="article?.body" />
</main>
</template>
※ bodyの表示で利用されている v-html はXSSの危険性があるため、利用には注意が必要です。ここでは、Newtで管理している投稿情報を表示するものであり、不特定多数のユーザーが入力できるものを表示するわけではないため、安全なものとして利用しています。
また、v-htmlを利用すると、eslintの警告が出る場合があるため <!-- eslint-disable-next-line vue/no-v-html -->
を記載しています。
これで、投稿詳細についての設定も完了です。
http://localhost:3000/articles/article-3
にアクセスして、以下のように投稿詳細が表示されれば成功です。
注意点
4-5で投稿詳細へのリンクとして、Nuxtの推奨している NuxtLink を利用しています。
本番環境で nuxt generate
を利用して、プリレンダリングを行えば問題なくページが作成されますが、開発環境の場合は一覧ページから詳細ページに遷移しても、ページが表示されません。
これは開発環境の場合、初期ロード時にサーバーサイドレンダリングが行われ、NuxtLink
での遷移時はクライアントサイドレンダリングが実行されるためです。
このチュートリアルでは、スペースUIDやトークンの値をクライアントサイドから隠すために、Newtのクライアントを newt.server.ts
ファイルで作成し、クライアントサイドでの読み込みを許可していません。そのため、ページ遷移をした時に投稿情報を取得できず、ページが表示されなくなってしまいます。
ページ遷移後にリロードを行えば問題なくページが表示されますが、ご注意ください。
次のステップ
このチュートリアルを行うことで、Nuxt3のプロジェクトを作成し、開発環境でコンテンツの取得・表示を行う方法を学習しました。
更に深く学習したい方は、以下のチュートリアルもおすすめです。
ホスティングを行いたい方
- GitHubのリポジトリとVercelを接続して、ホスティングする
- GitHubのリポジトリとNetlifyを接続して、ホスティングする
- GitHubのリポジトリとCloudflare Pagesを接続して、ホスティングする
問い合わせフォームを作成したい方
その他にも様々なチュートリアルを用意しているので、ぜひ チュートリアル のページもご確認ください。