Nuxt3でブログを作る
このブログを Nuxt2 で構築してから3年が経ち,Nuxt2 のサポートが終了するため,Nuxt3 で構築し直しました.
同様の投稿はたくさんあるので,要点のみ記載しています.
プロジェクト構築
下記ページを参考に Nuxt Content v2 のプロジェクトを作成します.
参考:Installation - Nuxt Content
ちなみに,コマンドには nuxi
と nuxt
が登場しますが,前者は Nuxt CLI として構築されたものです.
環境変数
Nuxt3 は dotenv がビルドインされています.
参考:.env · Nuxt Directory Structure
.env.local と .env.production など複数ファイルを用意することで,実行環境別に環境変数を設定できます.
ローカル環境では同一ネットワークから接続できるように,以下の環境変数を設定しておきます.
.env.local
HOST=0
PORT=3000
Preprocessors
Pug.js
terminal
$ yarn add pug
<template>
の lang
属性に pug
を指定すると,Pug.js が利用できます.
Sass
共通化したい Sass は assets
ディレクトリ内のファイルに書き出すと良いです.
ちなみに,Sass には SCSS と Sass が内包されています.SCSS は中括弧あり,Sass は中括弧なしです(なぜプリプロセッサと記述方式の名称を一緒にしてしまったのか…).
Modules
Nuxt3 では,Nuxt2 から引き続き,各機能をモジュールとして提供しています.一般的に必要な機能はほぼカバーされている印象です.
Nuxt UI
Nuxt2 では Bulma を利用していましたが,Bulma や Buefy は Nuxt3 に対応していないようだったので,Nuxt UI @nuxt/ui
に切り替えました.
Nuxt UI は Tailwind CSS をベースとしています.また,@nuxtjs/color-mode
と nuxt-icon
も自動で入ります.設定ファイルで有効化が必要です.
nuxt.config.ts
export default defineNuxtConfig({
modules: ['@nuxt/ui', '@nuxtjs/color-mode', 'nuxt-icon'],
})
デフォルトの色を変更したい場合は,既に用意されているカラーマップから選ぶか,カラーマップを作成して指定します.カラーマップを作成するには,以下のサイトが便利です(最高).
設定ファイルは,以下のコマンドを実行するとルートディレクトリ下に作成されます.
terminal
$ npx tailwindcss init --ts
コンポーネントが参照するカラーマップは,ルートディレクトリ下の app.config.ts で指定します.
Nuxt UI Pro にすると多くのコンポーネントが利用できますが,製品版で使うには課金が必要です.使えるコンポーネントは限られますが,課金せずに利用できるコンポーネントもあります.
ダークモード
上記の記述で有効になります.
Chrome ブラウザでは,DevTools の右上3点リーダーから More tools > Rendering > Emulate CSS media features prefers-color-scheme からエミュレートするモードを変更できます.動作確認に便利です.
@nuxtjs/color-mode
単体では,カラーモードを示すクラス名が light-mode
or dark-mode
ですが,@nuxt/ui
を有効にすると light
or dark
になります.
アイコン対応
<Icon>
タグで各種アイコンパッケージを楽に参照できます.
参考:GitHub - nuxt-modules/icon: The <Icon> component, supporting Iconify, Emojis and custom components.
上記では呼び出せないような SVG アイコンを利用したい場合は,nuxt-icons
パッケージを利用することもできます.名称は似てますが,別のパッケージです.
Syntax Highlighting
デフォルトで Shikiji という SyntaxHighlight に対応しています.対応言語や表示テーマは nuxt.config.ts に記述します.
参考:highlight
ライト/ダークモードの切り替えにも対応していますが,default
を設定すると常に優先して表示されてしまいます.
Nuxt Content v1 では,ファイル名の表示に対応していましたが,v2 ではデフォルトで対応していないようです.表示するには,コンポーネントを上書きする必要があります.
Open Graph 画像の自動生成
モジュールとして画像生成機能が提供されています.
デフォルトでは日本語非対応です.非英語圏の言語を利用する場合は,フォントを指定する必要があります.
参考:Non-English Locales · Nuxt SEO
多少制限はありますが,コンポーネントを作成する容量でイメージ画像を生成でき,Nuxt Devtools を併用するとリアルタイムで確認もできるので便利です.
フォントを日本語対応にすることはできますが,改行位置は調整されません.調整したい場合は,Google の BudouX などを用いて制御する必要があります.
前提としては,HTML タグの指示通りに画像を生成します.ただし,変換に対応していないスタイルも存在します.そのため,HTML 表示と画像生成時の見た目が異なることがよくあります.経験的に,改行の処理は認識されないように感じます.
(Og-image モジュールの内部処理では,複数のパッケージを用いて ReactNode → SVG → PNG と変換されていきます.)
generate
コマンドが画像を生成するとき,.nuxt
ディレクトリのキャッシュを参照するため,記事を変更しても画像が変更されません.キャッシュを削除すれば,次回実行時に再生成されます.
参考:nuxi cleanup · Nuxt Commands
Sitemap
Google Analytics
多言語対応
参考:GitHub - nuxt-modules/i18n: I18n module for Nuxt
プロジェクト編集
ディレクトリ構造
Directory Structure を参照してください.
参考:Nuxt Guide
layouts
複数のページで同一のレイアウトを利用したい場合に使います.プロジェクト作成時に生成されませんが,Nuxt2 から変わらず利用できます.
有効化には,app.vue の編集が必要です.
参考:layouts/ · Nuxt Directory Structure
composables と utils の使い分け
Nuxt3(Vue3)では, Vue の Composition API を利用する composable を用意できます.Composition API とは,状態を管理するロジックをカプセル化して再利用するためのものです.
composables 下のスクリプトは自動インポートされますが,utils ディレクトリ下のスクリプトも同様に自動インポートされます.utils には comspsables 用途以外のカプセル化した処理を格納します.
参考:utils/ · Nuxt Directory Structure
script setup
<template>
, <script>
, <style>
の3要素を含む .vue ファイルを Single File Component (SFC) と呼びます.
Vue3 から <script setup>
が使えるようになりましたが,<setup>
とは記述方法が異なります.従来よりも簡潔に記述できる場合が多く,型も定義しやすくなったようです.
<script>
はコンポーネントがインポートされた最初のタイミングで実行されますが,<script setup>
はコンポーネントのインスタンスが作成されるたびに実行されます.
雰囲気は以下の通りです.Nuxt2 を触ったことがあると,記述方法が大きく変わったことがわかると思います.詳しくは,公式ドキュメントを参照してください.
<template>
<div>
<p v-if="hasName">{{ name }}</p>
</div>
</template>
<script setup>
const props = defineProps({
name: {
type: String,
default: '',
},
})
const { name } = props
const hasName = computed({
get() {
return name === 'alice'
},
})
</script>
Markdown の取得
Nuxt Content v1 で利用できた $content
はなくなり,useAsyncData()
関数を利用する形になりました.
<script setup>
const { data } = await useAsyncData('home', () => queryContent('/').findOne())
</script>
この処理を複数並列して実行する場合,第一引数で管理されています.つまり,同じキーを指定すると結果が共有されます.
複数のコンポーネントが並列されているとき,親コンポーネントと子コンポーネントで上記の処理を行うときなどは,同じキーを利用していると最終的に変数に代入される値が同じになるため,注意が必要です.
参考:queryContent() - Nuxt Content
画像パスの動的な指定
Nuxt2 では,require()
関数で動的に指定していました.
<img :src="require(`~/assets/image/${name}.jpg`)" />
Nuxt3 では,Vite がこの関数に対応していないため,インポート方法を変える必要があります.試していませんが,下記のような方法があるようです.
参考:Nuxt3 で img タグの src 属性に変数を使えない問題の回避策 #JavaScript - Qiita
public ディレクトリ下の画像はパスが変わらないため,通常通りの記述で読み込めます.
<img :src="`/image/${name}.jpg`" />
上記は v-bind
の記載(省略形)になっていますが,文字列の中に変数を埋め込むように書くことも技術上は可能です.しかし,変数のバインディングが有効にならないため,undefined
になります.
実行環境
nuxt dev or preview
Nuxt3 では nuxt preview
が利用できますが,build
後に実行するコマンドで,start
と同一の処理を行います.
同一ネットワーク内からの接続
ローカルネットワークから接続できるように,起動スクリプトを追記します.ローカルサーバを起動しているパソコンだけでなく,同じネットワークに接続する他のパソコンやスマホからも接続できます.
package.json
{
"scripts": {
"local": "yarn dev --dotenv .env.local"
}
}
terminal
$ yarn local
検索エンジンやブラウザへの対応
favicon
Google のガイドラインによれば,48px の倍数で用意しなければならないとのこと.
しかし,Apple のガイドによれば,iPhone/iPad(Pro/mini/無印)/Mac ごとに異なるサイズを用意するようにともあります.
参考:App icons | Apple Developer Documentation
多数のアイコンを用意し,記述するのも面倒なので,サイズ指定が不要な SVG で対応します(サイトを作るたびに思う,各社はなぜサイズを細分化してしまうのかと).IE 他,一部ブラウザは対応しない可能性があります.
また,iOS/iPad OS の最高画質向けに,180x180 サイズの apple-touch-icon を別途用意します.Google のドキュメントに apple-touch-icon-precomposed も設定項目として表記されていますが,これは古い iOS 端末でアイコンに光沢が出ないようする項目のようです.
参考:apple-touch-icon と apple-touch-icon-precomposed - chocotaka の日記
rel="shortcut icon"
は古い記述のため,不要そうです.
参考:HTML attribute: rel - HTML: HyperText Markup Language | MDN
ちなみに,ICO ファイルは複数のサイズに対応できるため,単一ファイルで記述できる利点があります.
参考:sizes
Head 情報
OGP やその他メタデータなどを記載します.app.vue に記述すると,共通のタグとして利用されます.個別ページで設定すると,上書きされます.favicon などの <link>
もここで設定します.
参考:useSeoMeta
Feed
Nuxt3 では,フィードを作成するためのモジュールも公開されていますが,日本語記事を扱う Nuxt Content との相性が悪かったため,以下記事を参考にスクリプトを書きました.
参考:Nuxt Content V2 で RSS フィードを作成する - Yukii's Blog
最後に
Nuxt2 で作成したブログを Lighthouse で評価すると,以下のスコアでした.
Mobile
Reported by Lighthouse
PC
Reported by Lighthouse
Nuxt3 で構築し直した結果,スコアは少し減少しました.減少要因は,JS ライブラリの大きさや AdSense の仕様上の問題です.
Mobile
Reported by Lighthouse
PC
Reported by Lighthouse
Nuxt2 と比べてスクリプトは描きやすくなったと感じます(特に,props や method 周り).
Nuxt Content v1 は,開発サーバで起動しているとダブルクリックで Markdown 編集モードに入れましたが,v2 では無くなってしまったので軽微な編集はしづらくなってしまいました.
モジュールの拡充もあり,総じて見るとサイト構築がかなり楽になったと思います.