Nuxt.jsをインストール
まずはローカル環境でさわってみる。
プロジェクトを作成するディレクトリに移動する。(Node.jsはStrapi導入時にインストール済み)
公式サイトopen_in_newに載っているコマンドを実行してプロジェクトを作成。
$ npx create-nuxt-app fugafuga #fugafugaは任意のプロジェクト名
コマンドを実行すると対話形式で条件を訪ねてくるので、適当に入力/選択する。
create-nuxt-app v3.7.1
✨ Generating Nuxt.js project in fugafuga
? Project name: (fugafuga)
? Programming language: (Use arrow keys)
> JavaScript
TypeScript
? Package manager:
Yarn
> Npm
? UI framework: (Use arrow keys)
> None
Ant Design Vue
BalmUI
Bootstrap Vue
Buefy
Chakra UI
Element
Framevuerk
Oruga
Tachyons
Tailwind CSS
Windi CSS
Vant
View UI
Vuetify.js
? Nuxt.js modules: (Press to select, <a> to toggle all, <i> to invert selection)
>( ) Axios - Promise based HTTP client
( ) Progressive Web App (PWA)
( ) Content - Git-based headless CMS
? Linting tools: (Press to select, <a> to toggle all, <i> to invert selection)
>( ) ESLint
( ) Prettier
( ) Lint staged files
( ) StyleLint
( ) Commitlint
? Testing framework: (Use arrow keys)
> None
Jest
AVA
WebdriverIO
Nightwatch
? Rendering mode: (Use arrow keys)
> Universal (SSR / SSG)
Single Page App
? Deployment target: (Use arrow keys)
> Server (Node.js hosting)
Static (Static/Jamstack hosting)
? Development tools: (Press to select, <a> to toggle all, <i> to invert selection)
>( ) jsconfig.json (Recommended for VS Code if you're not using typescript)
( ) Semantic Pull Requests
( ) Dependabot (For auto-updating dependencies, GitHub only)
? What is your GitHub username? (github_username)
? Version control system: (Use arrow keys)
> Git
None
全て答えるとインストールがはじまる。
Installing packages with npm
︙
🎉 Successfully created project fugafuga
To get started:
cd fugafuga
npm run dev
To build & start for production:
cd fugafuga
npm run build
npm run start
インストール完了後に出てきた説明のnpmコマンドを打って起動してみる。
$ cd fugafuga #プロジェクトディレクトリに移動
$ npm run dev #開発モードで起動
︙
︙
✓ Client
Compiled successfully in 24.72s
✓ Server
Compiled successfully in 22.29s
i Waiting for file changes
i Memory usage: 156 MB (RSS: 188 MB)
i Listening on: http://localhost:3000/
http://localhost:3000/で確認できた。
remove [ components/Tutorial.vue ]
coding in [ pages/index.vue ]
とりあえずデフォルトの画面の説明を頭に入れておく。
Nuxt.jsの「apollo module 」をインストール
とりあえずGraphQLを扱うのに便利らしいので、先に「apollo module 」をインストールしておく。
一旦先ほど起動したNuxtを停止して、Nuxt CommunityのGitHubopen_in_newにあるコマンドを実行する。
作成したNuxtプロジェクトディレクトリで実行
$ npm install --save @nuxtjs/apollo
インストールしたら準備完了。次は構築に進む。
HTMLプロトタイプをNuxt.jsで表示する
API云々以前に、普通に自分で書いたHTMLをSSRで描画させるのすら分からない。
まずは予め作っておいたHTMLプロトタイプを、Nuxtで見れるようにする。
公式サイトTOPopen_in_newの特徴紹介を見ると色々あるが、まずは下記3つの情報を漁ればできそうな気がする。
- File-system Routing
Automatic routing and code-splitting for every page. - Strong Conventions
Efficient teamwork with a strong directory structure and conventions. - Components Auto-import
Use your components, Nuxt will import them with smart code-splitting.
作成したプロジェクト内のディレクトリやブラウザの表示なども見ておく。
Chrome拡張機能の「Vue.js devtoolsopen_in_new」を使うと把握しやすい。
ディレクトリ構成
作成したNuxtプロジェクト「fugafuga」の中身(細かいファイルなどは省略)
foldernode_modules #中は省略。apollo-moduleもココに追加された。
└ ︙
folder.nuxt #中は省略。
└ ︙
folderlayouts* #上記.nuxtディレクトリ内から持ってきた。
└ descriptiondefault.vue #共通テンプレート
folderpages #ページテンプレート:この中のディレクトリやファイルを自動でルーティング設定してくれる
└ descriptionindex.vue #Topページ
foldercomponents #ヘッダーとかフッターとか部品
├ descriptionNuxtLogo.vue
└ descriptionTutorial.vue
folderstatic #静的ファイルを置く、ドメインルート直下でアクセスできる
└ descriptionfavicon.ico
folderstore #とりあえず今は知らない
descriptionnuxt.config.js #共通設定ファイル
従来のCMS(WordPressとかMovableTypeとか)のテンプレートの感じでいけそう。
/layouts/default.vueとしているのは、元の場所でいじっても、buildするとデフォルトの内容に戻されたので外に出した。
なんとなく掴めた気はするので、プロトタイプのHTMLを分割して各vueファイルを作成する。
NuxtとVueの基礎知識(v2)
Vue.jsの知識もゼロなので、分割作業で調べたメモを参考までに。(将来更新するときの備え)
NuxtとVueのどっちのことなのかは区別できてないかもしれない。
- Vueファイル
1つのファイルに、HTMLとCSSとJavaScriptが書ける。
<template>内は1つのDOMツリーしか置けない。
今回はプロトタイプのCSSとScriptをVueファイルに合わせて分割するのが面倒なのでHTMLだけにした。<template> ︙ HTML 直下に兄弟要素を書けない。divとかでラップして1つのDOMツリーなら良い </template> <style> ︙ CSS </style> <script> ︙ JS, Vue </script>
- <head>~</head>内のtitleやmeta、外部ファイルの読み込みなど
全体で共通ならnuxt.config.jsに、特定のページだけなら該当ページのvueファイルの<script>~</script>内に書けばいい。
「body: true」を付けると</body>の直前になるexport default { head: { title: 'ベアマケR', meta: [ { charset: 'utf-8' }, { name: 'viewport', content: 'width=device-width, initial-scale=1' }, { hid: 'description', name: 'description', content: '' }, { name: 'format-detection', content: 'telephone=no' } ], script: [ { src: '/assets/js/hogehoge.js', defer: true }, { src: '/assets/js/console.log.js', body: true, defer: true } // </body>直前になる ], link: [ { rel: 'icon', type: 'image/svg+xml', href: '/favicon.svg' }, { rel: 'stylesheet', href: '/assets/css/common.css', async: true } ] } }
- <html>や<body>に属性を付けたい
全体で共通ならnuxt.config.jsに、特定のページだけなら該当ページのvueファイルに書けばいい。
export default { head: { htmlAttrs: { lang: 'ja' }, bodyAttrs: { id: 'hogehoge' } } }
- コンポーネントを読み込んで表示する
仮にheader.vueとfooter.vueのコンポーネントがあった場合。
/layouts/default.vue(全体共通テンプレート) <template> <div> <header /> headerコンポーネント表示 <Nuxt /> Nuxt仕様:ルーティングに応じたページのvueファイルを表示する <footer /> footerコンポーネント表示 </div> </template> <script> import header from '@/components/header.vue' import footer from '@/components/footer.vue' export default { components: { header, footer } }; </script>
GraphQLのデータを取得して表示する
今はコンテンツがテキストベタ打ちなので、StrapiのGraphQLで取得したデータを表示できるようにする。 この辺りの作業は、Strapiのブログの下記リンクの記事などが分かりやすい。
Strapiブログ:Build a blog with Nuxt (Vue.js), Strapi and Apolloopen_in_new
apollo moduleの設定
nuxt.config.jsにモジュールの使用とエンドポイントを設定する。
nuxt.config.js
export default {
︙
modules: [
'@nuxtjs/apollo'
],
apollo: {
clientConfigs: {
default: {
httpEndpoint: 'https://example.com/strapi/graphql'
}
}
},
︙
}
apollo moduleでGraphQLを取得する
GraphQLのクエリファイルを作成して、コンポーネントでデータを取得できる。
下記は記事一覧ページに、記事ID/カテゴリー名/記事タイトル/アイキャッチ画像を表示する例。(例は仮定のクエリ)
/queries/list.gql(クエリファイルを作成)
query List {
articles {
id
category
title
img {
url
}
}
}
/components/list.vue(記事一覧のコンポーネント)
<template>
<div>
<!-- v-forで記事データ分を繰り返し -->
<article v-for="article in reverseArticles" :key="article.id">
<span>article.category</span>
<h1><a v-bind:href="'/article/' + article.id">article.title</a></h1>
<!-- v-ifでデータが存在するときのみ表示(elseでデフォルト画像を表示でも) -->
<p v-if="article.img" ><img v-bind:src="'/strapi/' + article.img.url"></p>
</article>
</div>
</template>
<script>
import listQuery from '~/queries/list.gql' //クエリファイルをインポート
export default {
data() {
return {
articles: [] // クエリで取得のデータ定義
}
},
apollo: {
articles: {
prefetch: true,
query: listQuery // インポートしたクエリを指定
}
},
computed: {
reverseArticles() {
return this.articles.slice().reverse() //並び順を反転
}
}
}
</script>
次は記事詳細での例。
記事一覧と同様に、記事ID/カテゴリー名/記事タイトル/アイキャッチ画像を表示する例。(例は仮定のクエリ)
/queries/article.gql(クエリファイルを作成)
query Article($id: ID!) {
article(id: $id) {
id
category
title
img {
url
}
}
}
/pages/article/_id.vue(記事詳細のページコンポーネント)
<template>
<article>
<span>article.category</span>
<h1>article.title</h1>
<p v-if="article.img"><img v-bind:src="'/strapi/' + article.img.url"></p>
</article>
</template>
<script>
import articleQuery from '~/queries/article.gql' //クエリファイルをインポート
export default {
data() {
return {
article: {} // クエリで取得のデータ定義
}
},
apollo: {
article: {
prefetch: true,
query: articleQuery, // インポートしたクエリを指定
variables () {
return { id: parseInt(this.$route.params.id) } //クエリのID変数にURLパラメータのIDを指定
}
}
}
}
</script>
こんな感じでころがっている見本などを参考に書いていく。
NuxtとVueの基礎知識(v2)
データを反映する作業で学んだところのメモ。
- 動的ルーティング
NuxtのPages内の自動ルーティングで、ディレクトリ名やファイル名にアンダースコアを付けると動的なURLが生成される。/article/1, /article/2, /article/3 …など→/pages/article/_id.vueのようにファイル名に_を付ける。
- 親から子へのコンポーネント間のデータ受け渡し
親側で子コンポーネントにv-bindで送り、子側はpropsで受け取る。
HOMEのページコンポーネントで受け取ったURLのパラメーターを、記事一覧の子コンポーネントへ渡して一覧の絞り込み表示に使用した。(例:/?cats=1のパラメーターを使ってMAKEカテゴリで絞り込んだ記事一覧表示)これがいい方法なのかは分からないが。。 - asyncDataメソッド
ページコンポーネントでのみ使用可能。
ページの表示前にコンポーネントのデータをネットワークから取得できる、非同期データ機能。上記と同じく、HOMEでの記事一覧表示に使用。 - v-model(双方向データバインディング)
グローバルメニューでカテゴリやタグキーワードでの絞り込み選択時、記事数を表示するため使用。
おわりに
“YAGNI”で必要そうなものだけを情報収集した。単にNuxtとVueを学習するとなると壮大で大変そうだが、ただ表示できればいいだけなので思ったほど時間はかからずに済んでよかった。
公開後にNuxt3(Vue3対応)が出てしまった。ベータ版からアルファ版になったら、アップデートしないと。Strapiもv4のベータ版が出た。どちらも大変じゃありませんように…
次はいよいよ公開作業です。