NewtとNuxt3を利用してブログを作成する
Table of contents
- 記事内で使用している主なソフトウェアのバージョン
- 概要
- 1. Nuxt3のセットアップ
- 1-1. プロジェクトの作成
- 1-2. TypeScriptの設定
- 2. Newtのセットアップ
- 2-1. Appを追加する
- 2-2. スペースUID・App UID・モデルUIDを確認する
- 2-3. Newt CDN API Tokenを作成する
- 3. リクエストの準備
- 3-1. 環境変数の設定
- 3-2. newt-client-jsのインストール
- 3-3. プラグインの作成
- 4. 一覧ページの作成
- 4-1. 言語の設定をする
- 4-2. 投稿の型を定義する
- 4-3. NuxtPageを設定する
- 4-4. 投稿一覧を取得する
- 4-5. 投稿一覧を表示する
- 5. 詳細ページの作成
- 5-1. 投稿詳細を取得する
- 5-2. 投稿詳細を表示する
- 注意点
- 6. Vercelにデプロイする
- 次のステップ
このチュートリアルでは、Newtと Nuxt3 を利用して、ブログを作成する手順を紹介します。
具体的には、Newtで管理しているコンテンツの一覧ページと詳細ページを作る手順を紹介した後、Vercel にデプロイして、静的生成(SSG)でページを表示します。
記事内で使用している主なソフトウェアのバージョン
- Nuxt(
nuxt
): 3.10.3 - newt-client-js(
newt-client-js
): 3.3.0
概要
Nuxt3でプロジェクトを作成し、Newtのコンテンツ情報を取得できるようにします。
コンテンツの一覧ページ(パス: /
)と詳細ページ(パス: /articles/:slug
。slugがarticle-1の場合は /articles/article-1
)を作成し、ローカル環境で表示できるようにします。
続いて、Vercelにデプロイし、静的生成でページを表示します。
1. Nuxt3のセットアップ
1-1. プロジェクトの作成
はじめに、Nuxt3のセットアップを行います。以下のコマンドでプロジェクトを作成します。
<project-name>
には好きな名前を入力しましょう。ここでは nuxt3-blog
という名前で作成します。
npx nuxi init <project-name>
コマンドを入力すると、以下の質問を聞かれるので、お好きな設定を選びましょう。
- どのパッケージマネージャーを利用するか(ここでは
yarn
を選択) - gitリポジトリを初期化するか?(ここでは
Yes
を選択)
以下のように表示されます。
$ npx nuxi init nuxt3-blog
Need to install the following packages:
nuxi@3.10.1
Ok to proceed? (y)
✔ Which package manager would you like to use?
yarn
◐ Installing dependencies...
yarn install v1.22.22
info No lockfile found.
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
warning vscode-languageclient@7.0.0: The engine "vscode" appears to be invalid.
[3/4] 🔗 Linking dependencies...
warning "nuxt > @nuxt/devtools@1.0.8" has unmet peer dependency "vite@*".
warning "nuxt > @nuxt/devtools > vite-plugin-inspect@0.8.3" has unmet peer dependency "vite@^3.1.0 || ^4.0.0 || ^5.0.0-0".
warning "nuxt > @nuxt/devtools > vite-plugin-vue-inspector@4.0.2" has unmet peer dependency "vite@^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0".
warning "nuxt > @nuxt/devtools > @nuxt/devtools-kit@1.0.8" has unmet peer dependency "vite@*".
[4/4] 🔨 Building fresh packages...
success Saved lockfile.
$ nuxt prepare
✔ Types generated in .nuxt
✨ Done in 13.21s.
✔ Installation completed.
✔ Initialize git repository?
Yes
ℹ Initializing git repository...
Initialized empty Git repository in /Users/foo/bar/nuxt3-blog/.git/
✨ Nuxt project has been created with the v3 template. Next steps:
› cd nuxt3-blog
› Start development server with yarn run dev
作成したプロジェクトに移動して、開発サーバーを立ち上げます。
yarnを利用する場合は以下のようになります。
$ cd nuxt3-blog
$ yarn dev
http://localhost:3000
にアクセスして、以下のような画面が表示されることを確認します。
1-2. TypeScriptの設定
開発環境でも型のチェックを行うために、以下の設定を行います。
※ 開発環境で型のチェックを行わない場合は、1-2のステップを飛ばして構いません。
まず vue-tsc
・typescript
をdevDependenciesとしてインストールします。
yarn add -D vue-tsc@^1 typescript
さらに、nuxt.config.ts
ファイルで typescript.strict
オプションと typescript.typeCheck
オプションを有効にします。
export default defineNuxtConfig({
devtools: { enabled: true }
devtools: { enabled: true },
typescript: {
strict: true,
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で作成したトークンの値を定義します。以下を、実際の値で置き換えて定義してください。
1NUXT_NEWT_SPACE_UID=sample-for-docs
2NUXT_NEWT_CDN_API_TOKEN=xxxxxxxxxxxxxxx
あわせて、nuxt.config.ts
に以下のように runtimeConfig
の設定を追加します。
export default defineNuxtConfig({
runtimeConfig: {
newt: {
spaceUid: '',
cdnApiToken: ''
}
},
devtools: { enabled: true },
typescript: {
strict: true,
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
というファイルを作成します。
1import { createClient } from 'newt-client-js'
2
3export default defineNuxtPlugin(() => {
4 const config = useRuntimeConfig()
5 const newtClient = createClient({
6 spaceUid: config.newt.spaceUid,
7 token: config.newt.cdnApiToken,
8 apiType: 'cdn'
9 })
10 return {
11 provide: {
12 newtClient
13 }
14 }
15})
これで、Vueコンポーネント内から、Newtのクライアントを利用できるようになりました。
プラグインの詳細については、Nuxtの plugins のドキュメントをご確認ください。
4. 一覧ページの作成
4-1. 言語の設定をする
nuxt.config.ts
で lang 属性を設定します。ここでは日本語 ja
を指定します。
export default defineNuxtConfig({
app: {
head: {
htmlAttrs: {
lang: 'ja'
}
}
},
runtimeConfig: {
newt: {
spaceUid: '',
cdnApiToken: ''
}
},
devtools: { enabled: true },
typescript: {
strict: true,
typeCheck: true
}
})
4-2. 投稿の型を定義する
投稿の型 Article
を定義しておきます。
このチュートリアルでは、_id
・title
・slug
・body
のみを使うため、以下のように定義しておきます。
1export interface Article {
2 _id: string
3 title: string
4 slug: string
5 body: string
6}
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 を利用して、タイトルとディスクリプションを設定しています。
1<script lang="ts" setup>
2import type { Article } from '~/types/article'
3
4const { data } = await useAsyncData('articles', async () => {
5 const { $newtClient } = useNuxtApp()
6 return await $newtClient.getContents<Article>({
7 appUid: 'blog',
8 modelUid: 'article',
9 query: {
10 select: ['_id', 'title', 'slug', 'body']
11 }
12 })
13})
14const articles = data.value?.items
15
16useHead({
17 title: 'Newt・Nuxtブログ',
18 meta: [
19 { name: 'description', content: 'NewtとNuxtを利用したブログです' }
20 ]
21})
22</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
に以下の部分を追加します。
1<template>
2 <div>
3 <ul>
4 <li v-for="article in articles" :key="article._id">
5 <NuxtLink :to="`/articles/${article.slug}`">
6 {{ article.title }}
7 </NuxtLink>
8 </li>
9 </ul>
10 </div>
11</template>
http://localhost:3000/
にアクセスして、以下のように投稿一覧が表示されれば成功です。
5. 詳細ページの作成
5-1. 投稿詳細を取得する
Nuxtでは [param]
のようにしてページ名に角括弧を使うことで動的なルーティング(Dynamic Routes)を作成できます。ここでは、/articles/:slug
(/articles/article-1
など)のパスで投稿の詳細を表示したいので、pages/articles/[slug].vue
のファイルを作成します。
まず、script
タグに以下の内容を記載します。
投稿一覧の取得と同様に、useAsyncData を利用します。article
という変数で定義することで、template
の中で参照できるようにしています。
1<script lang="ts" setup>
2import type { Article } from '~/types/article'
3
4const route = useRoute()
5const { slug } = route.params
6
7const { data } = await useAsyncData(`article-${slug}`, async () => {
8 const { $newtClient } = useNuxtApp()
9 return await $newtClient.getFirstContent<Article>({
10 appUid: 'blog',
11 modelUid: 'article',
12 query: {
13 slug,
14 select: ['_id', 'title', 'slug', 'body']
15 }
16 })
17})
18const article = data.value
19
20useHead({
21 title: article?.title,
22 meta: [
23 { name: 'description', content: '投稿詳細ページです' }
24 ]
25})
26</script>
投稿詳細を取得するメソッドとして、SDKが提供している getFirstContent を利用しています。このメソッドはクエリに該当するコンテンツのうち、最初の1件を返却するメソッドです。指定したスラッグのコンテンツを取得したい場合は、このメソッドを利用します。
5-2. 投稿詳細を表示する
5-1で定義した article
を利用して、template内で投稿詳細を表示できるようにします。
pages/articles/[slug].vue
に以下の部分を追加します。
1<template>
2 <main class="main">
3 <h1>{{ article?.title }}</h1>
4 <!-- eslint-disable-next-line vue/no-v-html -->
5 <div v-html="article?.body" />
6 </main>
7</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
ファイルで作成し、クライアントサイドでの読み込みを許可していません。そのため、ページ遷移をした時に投稿情報を取得できず、ページが表示されなくなってしまいます。
ページ遷移後にリロードを行えば問題なくページが表示されますが、ご注意ください。
6. Vercelにデプロイする
最後に、Vercelへのデプロイを設定します。
まず、GitHubのリポジトリを作成し、これまで作成したコードをプッシュします。
詳細はGitHubの リポジトリを作成する のドキュメントをご確認ください。
続いて、作成したリポジトリとVercelを接続します。
※ Vercel のアカウントを持っていない方は、登録をお願いします。
接続方法の詳細については、GitHubのリポジトリとVercelを接続して、ホスティングする のチュートリアルを参考にしてください。
「Framework Preset」に「Nuxt.js」が設定されていることを確認し、「Build Command」に「nuxt generate」を指定しましょう。
また「Environment Variables」にご自身の環境変数を設定しましょう。
デプロイが成功し、サイトが表示されれば成功です!
次のステップ
このチュートリアルを行うことで、Nuxt3のプロジェクトを作成し、コンテンツの取得・表示を行う方法を学習しました。
更に深く学習したい方は、以下のチュートリアルもおすすめです。
Vercel以外でホスティングを行いたい方
問い合わせフォームを作成したい方
その他にも様々なチュートリアルを用意しているので、ぜひ チュートリアル のページもご確認ください。