本文書ではvue.jsのフレームワークNuxt.jsを使ってアプリケーションの開発を効率的に行いたいという人を対象にNuxt.jsのインストールから基本機能の動作確認の説明を行っています。

vue.jsのシンプルなコードのみで記述していますがvue.jsの知識があることを前提に説明を行なっているためvue.jsを知らない人には少し難しい内容になっています。

動作確認を行っているNuxt.jsのバージョンはv2.15.7です。

本文書を読み終えるとNuxt.jsに含まれる機能の基本的な使用方法を理解することができます。

別のJavaScriptのフレームワーク(ライブラリ)のReactにはNext.jsという似た名前のフレームワークがありますNext.jsに関する記事も公開しています。一文字違うだけなので間違えないようしてください。

Nuxt.jsとは

Nuxt.jsはvue.jsのフレームワークです。フレームワークは一般的に使用頻度の高い機能があらかじめ組み込まれて最適化されているため開発を効率的に行うことができます。例えばNuxt.jsにはルーティングのVue Routerやデータ管理のVuex、HTMLのメタタグ管理のvue-metaなどのプラグインを使用するために必要となる設定が事前に行われているため細かな設定を行う必要がなくすぐに利用することができます。

上記のプラグイン(ルーティング、データ管理、メタタグ管理)以外にもNuxt.jsを説明する際に使われる代表的な機能には次のようなものがあります。

  • Sever Side Rendering(サーバサイドレンダリング)
  • ディレクトリ構成
  • Code Splitting
  • SEOへの対策
本文書では実際に動作確認をしながらこれらの機能の理解を深めていきます。

Sever Side Rendering

vue.jsはJavaScriptで記述されているのでサーバからJavaScriptのファイルを受け取りブラウザ側でJavacriptの処理を行うことでページを描写します。例えばHTMLしか理解できないクローラーからサイトへのアクセスがあった場合、クローラーではJavaScriptの処理を行えないためvue.jsで作成されたページには何も記述されてないサイトと認識されてしまいます。Nuxt.jsではServer Side Rendering(サーバサイドレンダリング)という機能を利用してその問題を回避します。サーバーサイドレンダリングではJavaScriptのレンダリング処理(ブラウザで表示させる内容の処理)をブラウザを含むクライアント側で行うのではなくサーバ側で行いブラウザに渡します。そのため通常のHTMLのようにクローラーがページの中身を理解することができます。

ディレクトリ構成

ファイル数が少ない小規模のアリケーションの場合は問題になりませんが、アプリケーションの機能が拡張され、ファイル数が増えてくると作成したファイルをどのディレクトリに保存すべきかわからなくなり混乱してしまうことがあります。Nuxt.jsはベストプラクティスのディレクトリ構成が事前に組まれているのでその構成に従うことで効率よくコンポーネントやファイル管理を行うことができます。

Code Splitting

各ページに必要となるJavaScriptファイルのみ自動でクライアント側のブラウザに渡す機能です。アクセスしたページ内で使用しない余分なコードをブラウザに渡す必要がなくなるためパフォーマンスの向上を図ることができます。

ルーティングの設定

vue.jsでも Vue Router パッケージを個別にインストールすることでルーティング機能を追加することができますが、新たにルーティングを追加するとルーティングに関する情報を設定ファイル(router.js)に追加していく必要があります。

Nuxt.jsではページ用のディレクトリのpagesにページファイルを保存するだけでそのファイル名に対応するルーティングを自動で設定してくれます。ページを追加する度にVue Routerの設定ファイルrouter.jsファイルを更新する必要がありません。

SEOへの対策

ホームページやブログで利用する場合はアクセス数を増やすためSEO対策を行う必要があります。Nuxt.jsではプラグインのvue-metaが入っているため、SEOへの対策に必要なmetaタグの設定を簡単に行うことができます。

Nuxt.jsを使っているサイト

vue.js、nuxt.jsはさまざまなサイトで利用されています。Vue.jsを作ったEvan Youの以前の講演でルイヴィトンについて触れていました。

ルイビィトンでもNuxt.js
ルイビィトンでもNuxt.js

また最近では発足したばかりのデジタル庁のホームページにも利用されています。Nuxt.jsの動きを確認してみたいのであればデジタル庁のホームページにアクセスしてみるのもいいかもしれません。シンプルなサイトなので本書でNuxt.jsを勉強した後にデジタル庁のサイトのクローンを作成してみるのも勉強になるかもしれません。

デジタル庁のホームページはnuxt利用
デジタル庁のホームページはnuxt利用

Nuxt.jsの基礎

Nuxt.jsのインストール

Nuxt.jsのインストールはnpx create-nuxt-appコマンドで行うことができます。プロジェクトの名前は任意なので好きな名前をつけてください。ここではnuxt-firstと進めます。コマンドを実行するとインストールを進めるかどうか聞かれるので”y”を選択します。


$ npx create-nuxt-app nuxt-first
Need to install the following packages:
  create-nuxt-app
Ok to proceed? (y) 

インストール中は質問が行わられるのでその質問に答える形でインストールを進めていきます。

質問される内容も選択する項目も日々更新されています。本文書では2021年2月のcreate-nuxt-app v3.5.2で実行しています。

npx-nuxt-appでインストールを行うとNuxt.jsを構成するフォルダや設定が行われた状態でインストールされます。もしNuxt.jsをスクラッチからインストールしたい場合はnpm install nuxtでNuxt.jsをインストールすることも可能です。

プロジェクト名の入力

プロジェクト名を聞かれますがインストール時に入力したnuxt-firstがデフォルトの値として設定されるのでそのままEnterを押します。


create-nuxt-app v3.6.0
✨  Generating Nuxt.js project in nuxt-first
? Project name nuxt-first

■言語の選択

JavaScriptかTypeScriptのどちらを利用するか聞かれます。本文書ではJavaScriptを利用するのでそのままEnterを押します。


? Programming language: (Use arrow keys)
❯ JavaScript 
  TypeScript 

パッケージマネージャーの選択

yarnかnpmのパッケージマネジャーを選択します。使用するパッケージマネージャーを選択してください。本文書ではnpmを選択しています。


? Choose the package manager (Use arrow keys)
❯ Yarn 
  Npm 

UIフレームワークの選択

使用するUI(ユーザインターフェイス)のフレームワークを選択します。Bootstrap, Bulma, Vuetify.jsなどを選択することができます。使用予定のUIフレームワークを選択してください。本文書では何も利用しないのでNoneを選択しています。


? Choose 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 

モジュールの選択

使用するモジュールを選択することができます。これまでとは異なり、複数のモジュールが選択可能です。選択しなくても問題ありませんが、本文書ではAxiosのみ選択してインストールを進めます。


? Nuxt.js modules: (Press <space> to select, <a> to toggle all, <i> to invert se
lection)
❯◯ Axios - Promise based HTTP client
 ◯ Progressive Web App (PWA)
 ◯ Content - Git-based headless CMS

Lintツールの選択

Javscript, CSSの記述間違いやフォーマットの整形に利用できるLintを選択することができます。 モジュールと同様にすべて選択することも選択しないことも可能です。本文書では何も選択せずに進めます。


? Choose linting tools (Press <space> to select, <a> to toggle all, <i> to inver
t selection)
❯◯ ESLint
 ◯ Prettier
 ◯ Lint staged files
 ◯ StyleLint
 ◯ Commitlint

ESLint?ってという人には下記の文書がおすすめです。

ESLintをインストールしてsinglequoteやextra semicolonに関するエラーが発生した場合は下記のコマンドを実行することで自動修正を行ってくれます。


%  npm run lint:js -- --fix

テストフレームワークの選択

テストフレームワークを選択することができます。本文書では何も選択せずに進めます。


? Choose test framework (Use arrow keys)
❯ None 
  Jest 
  AVA 
  WebdriverIO 
  Nightwatch 

レンダリング方法の選択

Universal(SSR)とSingle Page Appの2つからレンダリング方法を選択することが可能です。SSRはServer Side Rendering(サーバーサイドレンダリング)の略です。Universal(SSR)を選択するとサーバ側でレンダリングを行い、Single Page Appを選択するとブラウザ側でレンダリングを行います。今回はUniversl(SSR)を選択します。


? Choose rendering mode (Use arrow keys)
❯ Universal (SSR) 
  Single Page App

■developementターゲットの選択

デプロイするターゲットを聞かれるますがNode.js hostingを選択します。


? Deployment target: (Use arrow keys)
❯ Server (Node.js hosting) 
  Static (Static/JAMStack hosting) 

developementツールの選択

Visual Studio Codeを利用している場合は、jsconfig.jsonを選択を行ってください。


? Development tools: (Press <space> 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)

■GitHubのユーザ名の入力

GitHubのユーザ名を聞かれるのでGitHubのユーザ名を入力します。そのまま何も名前を入力せずに進むこともできます。


? What is your GitHub username? 

■バージョンコントールの選択

Gitか何か利用しないか選択することができます。Gitを選択してEnterを押します。


? Version control system: (Use arrow keys)
❯ Git 
  None 

以上でインストールするために必要な質問は終わります。ここからパッケージのインストールが始まります。

インストールが完了すると以下の画面が表示されます。



🎉  Successfully created project nuxt-first

  To get started:

	cd nuxt-first
	npm run dev

  To build & start for production:

	cd nuxt-first
	npm run build
	npm run start

nuxt-firstディレクトリに移動して、npm run devコマンドを実行します。


$ cd nuxt-first/
$ npm run dev
 ・
 ・
   ╭───────────────────────────────────────╮
   │                                       │
   │   Nuxt @ v2.15.7                      │
   │                                       │
   │   ▸ Environment: development          │
   │   ▸ Rendering:   server-side          │
   │   ▸ Target:      server               │
   │                                       │
   │   Listening: http://localhost:3000/   │
   │                                       │
   ╰───────────────────────────────────────╯
ℹ Preparing project for development                                   
ℹ Initial build may take a while                                      
✔ Builder initialized                                                 
✔ Nuxt files generated                                                
✔ Client
  Compiled successfully in 4.29s

✔ Server
  Compiled successfully in 3.84s

ℹ Waiting for file changes                                            
ℹ Memory usage: 207 MB (RSS: 266 MB)                                  
ℹ Listening on: http://localhost:3000/   

ブラウザでlocalhost:3000にアクセスするとnuxt-firstの文字とNuxt.jsのロゴが表示された画面が表示されます。

Nuxt.jsの初期画面
Nuxt.jsの初期画面

Nuxt.jsのディレクトリ構成

インストールしたNuxt.jsがどのようなディレクトリ構成をしてどのようなファイルが保存されているのかを確認していきましょう。

プロジェクトディレクトリのnuxt_firstをVisual Code Editorで開きます。

Nuxtディレクトリ構成
Nuxtディレクトリ構成

.nuxtとnode_modeluesディレクトリを除きデフォルトで実行されるファイルが入っているディレクトリはlayouts, components, pagesとstaticのみです。そのほかのディレクトリはmdファイルのみ入っています。mdファイルには各ディレクトリの使用に関する簡単な説明が記載されています。

日本語訳を加えていますが例えばassetsのREADME.mdファイルには以下が記述されています。


# ASSETS

**This directory is not required, you can delete it if you don't want to use it.**
//このディレクトリは必須ではないので必要でないから削除することができる。

This directory contains your un-compiled assets such as LESS, SASS, or JavaScript.
//このディレクトリはLESS, SASS, JavaSCriptのコンパイルの行われていないアセットを保存します。

More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#webpacked).
//このディレクトリの使用方法についての詳細はリンクのドキュメントを確認してください。

layouts, pages, componentsディレクトリのファイルを確認するとデフォルトページの構成がわかります。ブラウザで確認したデフォルトのページは、layoutsのdefault.vue、pagesのindex.vue、componentsのlogo.vueファイルで構成されています。各ディレクトリには役割がありその中にファイルを保存することでアプリケーションを構築していきます。

トップページとvueファイルの関係
トップページとvueファイルの関係

layoutsディレクトリのファイルには各ページに共通となるナビゲーションバーやサイドバーなどアプリケーション全体のレイアウトに関するコードを記述するファイルを保存します。pagesはページ(URL)毎に異なる内容を記述するファイルを保存します。componentsディレクトリは再利用可能なコンポーネントファイルを保存します。そのためデフォルトでは再利用される可能性の高いLogo.vueファイルが保存されています。

上記の3つ以外のディレクトリにはどのようなファイルを保存していくのか説明しておきます。

  • assets・・・コンパイルが行われていないSASS, LESSやFontなどを保存
  • middleware・・・layoutやページがレンダリングする前に実行されるカスタム関数を保存。ユーザ認証などに使うことができます。
  • plugins・・・Vueインスタンスが起動する前にロードするJavaScriptプラグインを保存
  • static・・・robots.text, favicon、画像ファイルを保存されています。もしimage.pngを保存すると/image.pngでアクセスすることが可能です。
  • store・・・Vuex Storeに関するファイルが保存されています。
  • .nuxt・・・コンパイルを実行すると作成されます。
  • node_modelues・・・next.jsで使われるJavaScriptのパッケージが保存されています。

Nuxt.jsの動作確認

ここからは実際にファイルを追加/更新することでnuxt.jsの使い方を確認していきます。

ここからはnpm run devコマンドを実行した状態でファイルの追加/更新を行ってください。

pagesへのファイルの追加

新しいページを作成するためにpagesディレクトリの中にabout.vueファイルを作成します。


<template>
    <h1>About Page</h1>
</template>

ブラウザでlocalhost:3000/aboutにアクセスすると下記のページが作成されます。ルーティングを手動で追加する必要はありません。about.vueファイルを作成するとその名前に対応するURLに対して自動でルーティングが設定されます。

追加したaboutについてのルーティング情報は、.nuxtディレクトリのrouter.jsの中で確認することができます。


// 中略
export const routerOptions = {
  mode: 'history',
  base: decodeURI('/'),
  linkActiveClass: 'nuxt-link-active',
  linkExactActiveClass: 'nuxt-link-exact-active',
  scrollBehavior,

  routes: [{
    path: "/about",
    component: _15bd78f0,
    name: "about"
  }, {
    path: "/",
    component: _357553b5,
    name: "index"
  }],

  fallback: false
}

// 中略
nuxt.jsを利用せずvue-cliコマンドでVueプロジェクトを作成した場合は、コンポーネントを作成後にrouter.jsファイルにルーティングを手動で追加する必要があります。

ルーティングが自動で追加されているのでlocalhost:3000/aboutにアクセスするとabout.vueファイルに記述した内容が表示されます。

about.vueをpagesに作成後ブラウザでアクセス
about.vueをpagesに作成後ブラウザでアクセス

layoutsのdefault.vueの確認

layoutsディレクトリのdefault.vueファイルを中身を確認します。templateタグにはdivタグの中にNuxtタグが入っているだけです。このNuxtタグの部分にpagesの中のコンポーネントの情報が組み込まれることになります。その証拠にnuxtタグを削除するとブラウザには何も表示されません。


<template>
  <div>
    <Nuxt />
  </div>
</template>
NuxtタグがVue routerのrouter-viewと考えてください。

default.vueファイルにはNuxtタグ以外にもコンポーネントやhtmlタグを追加することができます。htmlタグを入力してどのような変化があるか確認してみましょう。


<template>
  <div>
    <nav>ここにナビゲーションバーを入れる</nav>
    <nuxt />
  </div>
</template>

“/”、”/about”のどちらのページアクセスしても上部に追加したテキストが表示されるのが確認できます。layoutsのファイルはpageコンポーネントの外側に存在しすべてのページで共通なコンポーネントとして存在することがわかります。

layoutsのdefalut.vueにテキストを追加
layoutsのdefalut.vueにテキストを追加

NavBarコンポーネントの作成

NavBarコンポーネント(NavBar.vue)を作成し、各ページへのリンクを作成します。NavBarコンポーネントはcomponetsディレクトリの下に作成します。リンクにはnuxt-linkタグを使います。vue-routerのrouter-linkに対応します。


<template>
  <div>
    <nav>
    <nuxt-link to="/">Home</nuxt-link>
    <nuxt-link to="/about">About</nuxt-link>
    </nav>
  </div>
</template>
nuxt-linkタグをrouter-linkタグに変更しても動作します。nuxt-linkでは後ほど出てくるprefetchの機能があります。ページを開かなくても先にそのページのJavaScriptファイルをFetch(取得)しておく機能です。またaタグに変更しても動作はしますが、リンクをクリックする度にブラウザのリロードが行われページを構成するすべての情報をリロード毎に取得します。通常のHTMLページ間での移動と同じ動作になります。

layoutsのdefault.vueに作成したNavBar.vueをimportします。デフォルトではdefault.vueにはscriptタグがないので追加してください。


<template>
  <div>
    <nav-bar />
    <nuxt />
  </div>
</template>

<script>
import NavBar from '@/components/NavBar.vue';
export default {
  components:{
    NavBar,
  }
}
</script>
//略

各ページの上部にHomeとAboutへのリンクが表示されます。ここまでの処理で簡単に個別ページとそれらのページへのリンクが貼れることがわかります。ボタンを押すとページがリロードすることなくスムーズにページを移動することができます。

NavBarを追加
NavBarを追加

別のレイアウトファイルの設定

default.vueファイルを使ってナビゲーションバーなどのページ共通のレイアウトを作成することができます。複数のページが存在する場合にdefault.vueではない異なるレイアウトを設定したい場合もあるかと思います。その場合にも別のファイルをlayousフォルダに作成することで対応することができます。

layoutsフォルダにoriginal.vueファイルを作成し、以下の内容を記述します。default.vueとはnuxtタグは共通ですがそれ以外は別のコンポーネントやタグを追加することができます。


<template>
  <div>
    <p>オリジナル</p>
      <nuxt />
    </p>
  </div>
</template>

別のレイアウトが作成できたら、それを利用するページファイルで作成したレイアウトを指定する必要があります。about.vueファイルにlayoutプロパティを追加し、値には作成したレイアウトファイルの名前を指定します。


<template>
  <h1>About Page</h1>
</template>
<script>
export default {
  layout: "original"
};
</script>

ブラウザで確認するとAbout Pageの上にオリジナルが表示された画面が表示されます。

オートインポート

Nuxt.jsはコンポーネントのオートインポートの機能を備えているので、Default.vueファイルので中ではcomponentsフォルダからNavBar.vueファイルのインポートを行っていましたがそれらのコードを削除してもNavBarコンポーネントを利用することができます。


<template>
  <div>
    <nav-bar />
    <nuxt />
  </div>
</template>
//スクリプトタグを削除

オートインポートの設定はNuxt.jsファイルのConfigファイルであるnuxt.config.jsから行うことができます。

nuxt.config.jsファイルを開きファイル中盤にcompoents:trueを見つけてください。componentsの値がオートインポートの設定を行います。


  // Auto import components: https://go.nuxtjs.dev/config-components
  components: false,

trueからfalseに変更を行ってください。左上に表示されていたリンクが消えるだけではなく中央にあったロゴも消えます。

オートインポート機能の確認
オートインポート機能の確認

実はindex.vueファイルで利用されているコンポーネントフォルダにあるLogo.vueファイルもオートインポート機能が利用されています。index.vueファイルの中にLogoタグはありますが、importの行はありません。

index.vueではLogoコンポーネントのimportの記述がないのにログが表示されていたので不思議に思っていた人もいるかもしれませんがオートインポートによりindex.vueファイルでのimportの明示なしでLogoコンポーネントを利用しています。

SSRの確認

nuxt.jsの特徴の1つであるSever Side Rendering(SSR)ですが、インストール時にUniversalを設定しているので自動で有効化されています。SSRを使用しないSingle Page Application(SPA)の場合とどのような違いがあるのか確認していきます。

SSRとSPAの設定変更

インストール後もnuxt.config.jsファイルのmodeパラメータを変更するとSSRとSPAの切り替えを行うことができます。パラメータの値はuniversalとspaの2つです。デフォルトではmodeパラメータはないので動作確認を行う際はmodeパラメータを下記のように追加する必要があります。


export default {
  mode: 'universal', //or spa

universalはSSRを使用、spaはSSRを使用しない設定です。

SSRの動作確認

SSRが実際に動作しているかどうかはdivタグにdata-server-rendered=”true”が設定されているかで確認できます。Chromeブラウザであれば”ページのソースを表示”で確認してください。

ブラウザからアクセスするURLは/aboutでファイルは下記のAbout.vueファイルを利用します。


<template>
  <div>
    <h1>Aboutページ</h1>
    <h2>{{ subtitle }}</h2>
  </div>
</template>

<script>
export default {
  data(){
    return {
      subtitle: 'この文書はNuxt.jsの基本的な使用方法について説明しています。'
    }
  },
}
</script>

SSR設定(universal)の場合はbodyタグの中にdata-server-rendered=”true”を見つけることができます。


<div data-server-rendered="true" id="__nuxt">

SSR設定なし(spa)の場合は、data-server-renderedタグを見つけることはできません。


<div id="__nuxt">

また、SSRの設定の場合はブラウザ上からページのソースを見ると通常のHTML文を確認することができます。SSR設定ありとなしでソースの内容が全く異なることをしっかり理解してください。


<div data-server-rendered="true" id="__nuxt">
  <div id="__layout">
    <div>
      <div>
        <nav>
        <a href="/" class="nuxt-link-active">Home</a> 
        <a href="/about" class="nuxt-link-exact-active nuxt-link-active">About</a>
        </nav>
      </div>
    <div>
    <h1>Aboutページ</h1> 
    <h2>この文書はNuxt.jsの基本的な使用方法について説明しています。</h2>
  </div>
</div>

SSR設定なしの場合は、上記のようなタグはページのソースを確認しても見つけることができません。このことからもSSRではサーバ側で処理が行われてページ情報が送信されていることがわかります。

違いをしっかり確認したい人はブラウザからのアクセスではなくcurlコマンドなどを利用してSSR設定ありとSSR設定なしで違いがわかるので実行してみてください。curl http://localhost:3000/aboutで実行可能です。

Code Splittingの確認

次はnuxt.jsの重要な機能の1つでもあるCode Splittingの動作確認を行います。

これまではコンパイルする際にnpm rum devで実行していましたが、今回はnpm run buildを実行します。buildは開発ではなくプロダクションの際に利用するコマンドです。


 $ npm run build

実行すると各ページに対応するJavaScriptファイルが作成されることがわかります。


Hash: 05e6076e1a50a9aa5a87
Version: webpack 4.41.2
Time: 2042ms
Built at: 2019-12-17 11:04:21
                  Asset       Size  Chunks                         Chunk Names
2814fe35faaaea370267.js  535 bytes       5  [emitted] [immutable]  pages/users/_id
29f5954878d4b3ae7aed.js  327 bytes       2  [emitted] [immutable]  pages/_category/index
58af663e6a323ef3e634.js   3.13 KiB       4  [emitted] [immutable]  pages/index
5a43840719e5e546f15b.js  348 bytes       1  [emitted] [immutable]  pages/_category/_article
5b0826655db24e4715d9.js  447 bytes       3  [emitted] [immutable]  pages/about
b128386ad9c15e74cdcd.js  272 bytes       6  [emitted] [immutable]  pages/users/list
              server.js   28.1 KiB       0  [emitted]              app
   server.manifest.json  435 bytes          [emitted]              
Entrypoint app = server.js

Code Splittingでページ毎に分けられたJavaSciptファイルはそのページに対応するJavaScriptファイルのみブラウザに送信されてくるのかを確認してみましょう。

v2.4.0からはviewportに<nuxt-link>タグが入っている場合は、自動でprefetchされます。そのためルートにアクセスすると<nuxt-link>タグでリンクされているAboutページのJavaSciptファイルも一緒に取得されます。prefetchされないように設定することが可能です。nuxt-linkタグにno-prefetchを設定します。


<nuxt-link to="/about" no-prefetch>About</nuxt-link>

no-prefetchを設定したら、npm run buildとnpm run startを実行します。

JavaScriptファイルの受信についてはブラウザの開発ツールのネットワークを利用します。

まずトップページへのアクセスを行います。開発ツールのNetworkを見ると6つのファイルが送られてきていることが確認できます。一番最後はfavicon.icoです。

トップページをアクセスした時に送られてくるデータ
トップページをアクセスした時に送られてくるデータ

次にトップページにあるリンクからaboutページへアクセスします。アクセスした瞬間にfavicon.icoの下に1つ増えていることが確認できます。

トップからaboutページに移動
トップからaboutページに移動

中身を確認するとAboutページに関するJavaScriptファイルであることがわかります。

送られてきたファイルの中身
送られてきたファイルの中身

これらの結果からCode Splittingでページ毎に分割されたJavaScriptファイルはアクセスするページ毎にそのページに対応するJavaScriptファイルを送信することがわかりました。

ルーティングの設定

先ほどAboutページを作成することでルーティングについて説明を行いましたが、もう少し掘り下げてnuxt.jsの特徴の1つでもあるルーティングの自動設定を確認していきます。

実際にページを作成しながらどのような動作になるのかみていきましょう。

階層ページを作成

Aboutページはpagesディレクトリの直下にAbout.vueファイルを作成してブラウザからURL:/aboutでアクセスすることでAboutページの内容を表示することができました。次はURLが/users/listという階層のある場合のルーティング方法について確認します。

pagesディレクトリの中にusersディレクトリを作成し、その下にlist.vueファイルを作成します。


<template>
    <h1>ユーザ一覧</h1>
</template>

nuxt.jsが自動でルーティングを作成してくれるので、ファイル作成後ブラウザで/users/listにアクセスするとlist.vueのtemplateタグに記述した内容が表示されます。このようにnuxt.jsを利用すると階層的なルーティングも自動で行ってくれます。

usersの下にlist.vueファイルを作成
usersの下にlist.vueファイルを作成

.nuxtディレクトリのrouter.jsファイルを確認すると追加したuserのlist情報が追加されています。


routes: [{
  path: "/about",
  component: _15bd78f0,
  name: "about"
}, {
  path: "/users/list",
  component: _06ba341c,
  name: "users-list"
}, {

routes.jsファイルに記述されているルーティングの名前users-list(name:”users-list”)を使ってNavBar.vueにリンクを追加します。router-linkタグと同様にnuxt-linkでもnameを使ってリンクを設定することが可能です。


<template>
  <div>
    <nav>
    <nuxt-link to="/">Home</nuxt-link>
    <nuxt-link to="/about">About</nuxt-link>
    <nuxt-link :to="{ name: 'users-list' }">User List</nuxt-link>
    </nav>
  </div>
</template>

ブラウザで確認するとUsersのリンクが追加され、クリックするとユーザ一覧が表示されます。

nameでリンクを設定
nameでリンクを設定

Dynamic Routes(動的ルート)

listではユーザの一覧を表示させるページでしたが、/users/1、/users/2のようにid(パラメータ)を受け取ってユーザ毎のページを作成したい場合はどのように行えばいいのでしょう。

_id.vueをusersディレクトリの下に作成することで実現することができます。

ファイル名は必ず_id.vueである必要はなくusernameをパラメータとして受け取る場合は_username.vueと任意の名前をつけることができます。ファイル名の前には必ず_(アンダーバー)が必要です。

/users/1, /users/2のようにURLに入力したIDは、this.$route.params.idで取得することが可能です。_id.vueファイルでIDを取得し、ブラウザに表示させます。


<template>
    <h1>ユーザID: {{ this.$route.params.id }}</h1>
</template>

/users/38でアクセスするとブラウザ上にはthis.$route.params.idで取得したIDが表示されます。

dynamic routesによるIDの取得
dynamic routesによるIDの取得

通常はaxios等でサーバから取得したデータを使ってusersの一覧を取得しますが今回はusersデータを予め用意してアクセスしてきたIDを使って表示するユーザ情報を変えます。


<template>
    <h1>ユーザID: {{ user.name }}</h1>
</template>

<script>
export default {
    data(){
        return {
            id: this.$route.params.id,
            users: [
                { 
                    id: 1, name: 'John Doe'
                },
                {
                    id: 2, name: 'Kevin Smith',
                },
                {
                    id: 3, name: 'Harry Bosch'
                },
            ],
        }
    },
    computed:{
        user(){
            return this.users.find(user => user.id == this.id);
        } 
    }
}
</script>

computedプロパティでブラウザで入力されたIDとデータプロパティのusersのidをチェックしています。/users/2でアクセスするとusersの中でidを2を持つユーザ名が表示されます。

dataプロパティとcomputedプロパティを利用
dataプロパティとcomputedプロパティを利用

this.$routeの中身

/user/2にアクセスするとthis.$routerparams.idからURLに入力した”2″の値を取得することができることがわかりました。ライフサイクルフックmountedを利用してthis.$routeにはどのような値が入っているのかも確認しておきましょう。


mounted() {
  console.log(this.$route);
}

オブジェクトの中にはparamsだけではなくfullPathなどの情報を保存されていることがわかります。$routeからparams以外の値も取得できることがわかりました。

$routeの中身
$routeの中身

ライフサイクルフックcreated

先ほどはthis.$routeの中身を確認するためにライフサイクルフックのmountedを利用しましたがcreatedを利用して情報を取得してみましょう。


created() {
  console.log(this.$route);
}

mountedフックとは異なり、Nuxt SSRという名前でメッセージが表示されます。SSRはServer Side Renderingの略でサーバ側でも同様にconsole.logの情報を出力することができます。サーバ側とクライアント側で2つの同じ内容が表示されています。

ライフサイクルフックcreated
ライフサイクルフックcreated

npm run devコマンドを実行しているコンソールにもthis.$routeの情報が表示されます。

nuxt.jsはmountedはクライアント側だけで実行され、createdはサーバ側とクライアント側で実行されることがわかりました。

複数のパラメータを受け取り

例えばブログサイトの階層(/{カテゴリー名}/{記事名})のようにURLから2つのパラメータ(カテゴリー名、記事名)を受け取りたい場合の方法を確認します。

pagesディレクトリに_categoryフォルダを作成しその中に_article.vueファイルを作成します。

作成後、/vue/start_nuxt_jsというURLにアクセスすると”vue”はthis.$route.params.category, “start_nuxt_js”はthis.$route.parames.articleで取得することができます。

/vue/にアクセスしてカテゴリーvueの記事一覧のみ取得したい場合は_categoryディレクトリの下にindex.vueファイルを作成することでthis.$route.parames.categoryからカテゴリーvueを取得可能です。


<template>
  <h1>カテゴリー:{{ this.$route.params.category }}</h1>
</template>

<template>
  <h1>{{ this.$route.params.category }}/{{ this.$route.params.article }}</h1>
</template>

prefetchの設定

nuxt-linkタグを利用することでデフォルトでprefetchの機能を利用することができます。prefetchはviewportに入ったリンクのデータをページにアクセス前に事前に取得できる機能です。

nuxt-linkタグでprefetchを停止したい場合はno-prefetchかPropsのprefectchの値をfalseに設定します。


<NuxtLink to="/about" no-prefetch>About page not prefetched</NuxtLink>
<NuxtLink to="/about" :prefetch="false">About page not prefetched</NuxtLink>

グローバルにprefectの停止を行いたい場合はnuxt.config.jsファイルで設定を行います。


  router: {
    prefetchLinks: false
  }

グローバルで停止したprefetchをあるリンクだけ実行したい場合はprefetchを以下のように設定することで可能です。


<NuxtLink to="/about" prefetch>About page not prefetched</NuxtLink>

prefetchの設定方法がわかったけど実際にどのような動作で本当にprefetch機能は動作しているのか知りたいという人もいるかと思います。動作確認は簡単なのでprefetchを理解するためにも自分で一度動作確認を行なってください。

prefectを設定している場合の動きを確認します。ブラウザのデベロッパーツールのネットワークタブを開いてトップページでリロードを行なってください。

ダウンロードされるjavascriptファイルの中にabout.jsファイルが存在することが確認できます。

Nuxt.jsのprefetch
Nuxt.jsのprefetch

次にダウンロードの履歴を削除するためにクリアボタンをクリックしてください。駐車禁止マークのようなボタンです。

ダウンロード履歴を削除
ダウンロード履歴を削除

ネットワークタブの履歴がクリアされるのでクリアした後にaboutページのリンクをクリックして移動してください。移動してもネットワークタブには何も表示されません。prefetchの設定(デフォルト設定)を行っている場合ではトップページにうアクセスするとabout.jsファイルがダウンロードされaboutページに移動しても何もダウンロードが行われないということがわかりました。

次にprefetchの機能を停止します。NavBarのaboutページへのnuxt-linkタグにno-prefetchを追加します。


<nuxt-link to="/about" no-prefetch>About</nuxt-link>

トップページに行きリロードしてデベロッパーツールのネットワークタブを確認してください。先ほどに表示されていたabout.jsファイルが表示されなくなりました。

prefecthを解除後のネットワーク状況
prefecthを解除後のネットワーク状況

次にダウンロードの履歴をクリアしてAboutページに移動してネットワークタブを確認します。今後はabout.jsファイルがAboutページにアクセスしたからダウンロードされることがわかります。

about.jsファイルがダウンロード
about.jsファイルがダウンロード

これらの2つの結果からprefetchを設定している場合はアクセス前に事前にabout.jsファイルをダウンロードすることがわかりました。

SEO対策

nuxt.jsではvue-metaライブラリを利用しています。metaタグにはさまざまなものがありますが、ここではtitleとdescriptionタグに注目して設定方法を確認していきます。

デフォルトの設定は、nuxt.config.jsファイルに記述されています。descriptionなどの値は他のページで上書きすることがあるので重複するのを避けるため識別子としてhidを設定しています。


  /*
  ** Headers of the page
  */
  head: {
    title: process.env.npm_package_name || '',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: process.env.npm_package_description || '' }
    ],
    link: [
      { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
    ]
  },

headによるtitleタグ追加

作成したAboutページのタイトルを見るとデフォルトのnuxt-firstが設定されています。タイトルはブラウザのタブで確認することができます。

デフォルトのタイトル
デフォルトのタイトル

About.vueファイルのscriptタグの中にheadプロパティを追加して、titleをAbout Pageに設定します。


<template>
    <h1>About Page</h1>
</template>

<script>
export default {
    head(){
        return {
            title: 'About Page',
        }
    }
}
</script>

ブラウザで確認するとタブがAbout Pageになっていることが確認できます。

titleタグ、metaタグはブラウザからページのソースや開発ツールのElements(要素)を見ることで確認することができます。
titleタグがAbout Pageに
titleタグがAbout Pageに

dynamic routesのページにおけるタグの追加

ルーティングで設定したuserの個別ページにtitleタグをつける方法を確認します。computedプロパティを利用することで動的にtitleを変更することが可能です。


export default {
  head(){
    return{
      title: this.user.name,
    }
  },
  data(){
    return {
      id: this.$route.params.id,
      users: [
        { 
            id: 1, name: 'John Doe'
        },
 //中略
      ],
    }
  },
  computed:{
    user(){
      return this.users.find(user => user.id == this.id);
    } 
  }
}

metaタグのdescription設定

metaタグのdescriptionに記述した内容はtitleと同様にSEOでは非常に重要はタグです。descriptionにはページの要約を記述します。

titleと同様にheadプロパティの中に記述します。


<script>
export default {
  head(){
    return {
      title: 'Aboutページ',
      meta:[
        { hid: 'description', name: 'description', content: 'これはAboutページです。'}
      ]
    }
  }
}
</script>

descriptionはブラウザ上には表示されないので、ページのソースを見ることで確認することができます。

ソースからdescriptionを書くにする

nuxt.config.jsでのメタタグ設定

nuxt.config.jsファイルにmetaタグに関する設定を確認することができます。各ページでheadを設定しない場合はこの値が各ページに利用されます。各ページの設定はローカル設定と呼ばれnuxt.config.jsでの設定はグローバル設定と呼ばれます。


export default {
  // Global page headers: https://go.nuxtjs.dev/config-head
  head: {
    title: 'nuxt-first',
    htmlAttrs: {
      lang: 'en'
    },
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: '' }
    ],
    link: [
      { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
    ]
  },

ブログなどのページでは”ページ名 | サイト名”という形式でtitleが設定される場合がよくあります。この場合はグローバル設定とローカル設定を組み合わせることができます。titleTemplateを下記のように利用します。%sに各ページのtitleが入ります。langもenからjaに設定しておきましょう。


  head: {
    title: 'nuxt-first',
    titleTemplate: "%s | Nuxt-First",
    htmlAttrs: {
      lang: 'ja'
    },

ブラウザで確認するとタブに”Aboutページ|Nuxt-First”と表示され期待した表示になっていることが確認できます。

Nuxt.jsのタイトルの設定
Nuxt.jsのタイトルの設定

langについてはソースを見ることで”en”から”ja”に変更されていることが確認できます。

langの変更はソースで確認
langの変更はソースで確認

Single Page Applicationモードの場合のタグ

nuxt.config.jsファイルのmodeパラメータをuniversalからspaに変更するとタグがどのように変化するのか確認してみましょう。


export default {
  mode: 'spa', // or universal

ページのソースコードを見るとデフォルトのThis is a first nuxt.js project”が表示されます。しかし、開発ツールのElementでタグを確認すると”これはAboutページです。”になっています。

理由はSever Side Renderingではmetaタグが設定された状態でクライアント側にページデータが送信されますが、Single Page Applicationの場合はページデータが送られた後にJavaScriptによってmetaタグが更新されるためです。ここからもSever Side Renderingではサーバ側で処理が行われることを示しています。

ここまでの内容で最初に上げたnuxt.jsの機能であるSever Side Rendersing, ディレクトリ構成、Code Splitting, SEOの対策, ルーティングの設定について説明を行うことができました。次は下記の文書でaxiosの使い方を確認しておきましょう。

その他

npm run buildコマンド

プロダクション用にビルドするためにはnpm run buildコマンドを実行します。npm run devとは異なりさまざまなファイルが作成されます。javascriptファイルにはアルファベットと数字が含まれるランダムな名前がつけられています。javascriptファイルが同じ名前である場合はブラウザのキャッシュに保存されているファイルは更新されません。毎回異なるファイル名が付けられるためキャッシュの問題を避けることができます。


 % npm run build
//略
Hash: 1566ea56592fdc7c3d81
Version: webpack 4.46.0
Time: 6564ms
Built at: 2021/06/16 10:53:35
                         Asset       Size  Chunks                         Chunk Names
../server/client.manifest.json   9.08 KiB          [emitted]              
                    073471e.js   58.5 KiB       0  [emitted] [immutable]  app
                    1b46a97.js   3.03 KiB    4, 2  [emitted] [immutable]  pages/index
                    5ba75f5.js   1.43 KiB       2  [emitted] [immutable]  components/logo
                    7bdd669.js    209 KiB       1  [emitted] [immutable]  commons/app
                      LICENSES  407 bytes          [emitted]              
                    c6fff5e.js   2.32 KiB       5  [emitted] [immutable]  runtime
                    e9c3b69.js  283 bytes       3  [emitted] [immutable]  pages/about
 + 2 hidden assets
Entrypoint app = c6fff5e.js 7bdd669.js 073471e.js

Hash: d2b584bee43fb7f53532
Version: webpack 4.46.0
Time: 572ms
Built at: 2021/06/16 10:53:35
               Asset       Size  Chunks             Chunk Names
  components/logo.js    5.4 KiB       1  [emitted]  components/logo
      pages/about.js   1.17 KiB       2  [emitted]  pages/about
      pages/index.js   11.5 KiB    3, 1  [emitted]  pages/index
           server.js   88.6 KiB       0  [emitted]  app
server.manifest.json  391 bytes          [emitted]  
 + 4 hidden assets
Entrypoint app = server.js server.js.map
ℹ Ready to run nuxt start 

ビルド後にnpm startコマンドを実行します。npm run devコマンドとは異なりビルドが完了しているのですぐに起動します。npm startコマンドで起動している場合はファイルの更新を行ってもnpm run devコマンドの実行時のようにホットリロードでリアルタイムに更新させることはありません。更新した内容を反映させるためには再度npm run buildを実行してビルドする必要があります。npm startコマンドを再実行しても変更は反映されません。

チルダによるパス設定

dataフォルダを作成してjsonファイルを用意した場合にそのファイルの内容を取得する際にimportを利用します。チルダをつけることでプロジェクトフォルダをルートとしたパスを設定することができます。


import users from '~/data/users.json'

チルダを利用しない場合はimportするファイルからの相対パスを設定する必要があります。/components/user/のしたいにファイルからimportしたい場合。


import users from '../../data/users.json'