関連:
Vueチートシートに引き続き公式チュートリアルの抜粋です。
参照
概要
-
Nuxt.js = Vue.jsおよびそのプラグインに基づくサーバサイドフレームワーク
- NuxtはVue.js, vue-router, vuex, Vue Server Render, Vue Metaなどを包含する
- Vueと同じく部分的に利用することができる(Progressive Framework)
-
公式によると以下のような機能を提供している:
- Vue ファイルで記述できること(*.vue)
- コードを自動的に分割すること
- サーバーサイドレンダリング
- 非同期データをハンドリングするパワフルなルーティング
- 静的ファイルの配信
- ES2015+ のトランスパイレーション
- JS と CSS のバンドル及びミニファイ化
- 要素(、 など)の管理
- 開発モードにおけるホットリローディング
- プリプロセッサ: Sass, Less, Stylus など
- HTTP/2 push headers ready
- モジュール構造で拡張できること
-
SSRの実現を主目的として導入されることが多いが、単純なSPAとして動作させることもできる
-
jekyllのようにVueコンポーネントから静的サイトをビルドすることもできる
-
Node.jsベースで動作する
- AppフレームワークとしてExpressをはじめとした複数を選択できる
- UIフレームワークも同様にBootstrap, Element UIなどを選択できる
- テストフレームワークも同様
導入
-
npx を使ってNuxtプロジェクトを簡単に作成できる
# npm5.2+はデフォルト $ npm install -g npx # インタラクティブに入力してプロジェクトを作成する # App/UI/テストフレームワークもここで選べる # yarn create nuxt-app <project-name> でも同じ $ npx create-nuxt-app <project-name> # 開発環境を起動 $ npm run dev
-
既存のプロジェクトに導入する場合はnpmパッケージとしてインストールする
package.json// npm run devでnuxtが立ち上がるように設定しておく { "name": "my-app", "scripts": { "dev": "nuxt" } }
$ npm install --save nuxt
基礎
ディレクトリ構造
Nuxtのプロジェクトは以下のようなディレクトリ構成をとる:
path | includes | memo |
---|---|---|
/assets/ |
CSS(SASS), 画像, フォントファイルなど静的なファイル | |
/components/ |
Vueコンポーネント | |
/layouts/ |
アプリケーションレイアウト | |
/middleware/ |
ミドルウェア(ページレンダリング以前に実行される処理) | |
/pages/ |
ViewおよびRouter | これ以下のファイル構成をもとにしてRoutingを作成する |
/plugins/ |
Vueのinstanciateより前に実行したい処理 | |
/static/ |
サーバのroot直下に直接配置されるファイル | faviconやrobots.txtなど |
/store/ |
Vuexストアファイル | |
/nuxt.config.js |
Nuxtの設定 |
ディレクトリエイリアス
- Nuxt Appにおいて
~
あるいは@
はソースが格納されるディレクトリ(srcDir) を示す-
~~
,@@
はrootDir - srcDirとrootDirはデフォルトでは等値
-
設定の分類
/nuxt.config.js
の設定は以下のようなトップレベルのキー以下に分類される:
category | includes | memo |
---|---|---|
build |
webpackを含むビルドオプション | |
css |
共有するCSSファイル/ライブラリの設定 | |
dev |
Dev/Prodモード | |
env |
環境変数 | |
generate |
routing | |
head |
meta-tagの設定 | |
loading |
ローディングコンポーネントの設定 | |
modules |
Nuxtモジュールの設定 | |
modulesDir |
node_modulesの所在 | |
plugins |
plugins/ 以下の設定 | |
rootDir |
Nuxtアプリケーションのroot | |
router |
Vue Router設定 | |
server |
サーバの設定 | |
srcDir |
ソースの所在 | |
dir |
カスタムディレクトリの設定 | |
transition |
トランジションの設定 |
Routing
Nuxtはvue-routerを用いてページをルーティングする
ルーティングの自動生成
-
/pages/
内のファイル・ディレクトリ構造に基づいて、自動的に設定を生成するたとえばこんなファイル構成だとpages/ index.vue users/ index.vue
このようになるrouter: { routes: [ { name: 'index', path: '/', component: 'pages/index.vue' }, { name: 'users', path: '/users', component: 'pages/users/index.vue' }, ] }
Link
-
ページ間の遷移は
<router-link>
ではなく<nuxt-link>
を使う<nuxt-link to="/">Home</nuxt-link>
パラメータ
-
URLにパラメータを含める場合はファイル名にアンダースコアをつける
pages/ users/ _id.vue posts/ _id/ index.vue
router: { routes: [ // こうするとパラメータが必須でなくなる(?) { name: 'users-id', path: '/users/:id?', component: 'pages/users/_id.vue' }, // 必須にしたい場合はディレクトリを切る { name: 'posts-id', path: '/posts/:id', component: 'pages/posts/_id/index.vue' }, ] }
-
パラメータを検証することができる
- 検証失敗した場合、Nuxtサーバは404を返す
- あるいはエラーがthrowされた場合は500を返す
アンダースコアから始まる(パラメータを含む)ページの.vueファイルexport default { validate({ params }){ // 戻り地の真偽をもって検証の可否とする return params.id > 0 } }
ネスト
-
ページをネストする場合は、リンクと同様に
<router-view>
ではなく<nuxt-child>
を親コンポーネントに配置するpages/ users/ _id.vue index.vue users.vue
// users.vueに <nuxt-child> を配置しておく必要がある router: { routes: [ { path: '/users', component: 'pages/users.vue', children: [ { path: '', component: 'pages/users/index.vue', name: 'users' }, { path: ':id', component: 'pages/users/_id.vue', name: 'users-id' } ] } ] }
未知のパスをハンドルする
-
_.vue
ファイルを配置すると、その他にマッチしなかった全てをハンドルできる# / はindex.vue # /users/ はusers/ # /foo などそれ以外は _.vue pages/ _.vue index.vue users/
View
Appテンプレート
-
全てのViewに共通するHTML(Appテンプレート)を定義できる
- Appテンプレートは
/<rootDir>/app.html
として配置する
/app.html<!-- こんなふうに定義しておく(以下はNuxtのデフォルトのAppテンプレート --> <!DOCTYPE html> <html {{ HTML_ATTRS }}> <head {{ HEAD_ATTRS }}> {{ HEAD }} </head> <body {{ BODY_ATTRS }}> {{ APP }} </body> </html>
- Appテンプレートは
Layout
-
デフォルトのレイアウトは
/layouts/default.vue
である/layouts/default.vue<!-- nuxtタグにページがレンダリングされる --> <template> <nuxt /> </template>
-
レイアウトをカスタムしたい場合は
/layouts
にファイルを配置する/layouts/custom.vue<template> <!-- ...カスタムされたレイアウト --> <nuxt /> </template>
-
カスタムレイアウトはページ側で指定することで利用できる
export default{ layout: 'custom' }
-
App内でエラーが発生した場合のエラーページは、レイアウトのひとつ(
error.vue
)として定義しカスタムできる- エラーページの例は 公開されている
ページ
-
Nuxt上のページ(Vueコンポーネント)は、SSRのために追加の機能が提供されている
page.vue<template> <h1 class="red">Hello {{ name }}!</h1> </template> <script> export default { // コンポーネントのロードの都度呼ばれる // 非同期で実行でき、戻り値はdataオブジェクトとマージされる asyncData (context) { return ... }, // ページの描画前にstoreを初期化する fetch () { // ... }, // <meta> を設定する head () { // ... }, // レイアウトを設定する layout: 'custom', // 遷移時のアニメーションを設定する loading: false, // 遷移時にスクロールを一番上に戻すか scrollToTop: true, // トランジションの設定 //transition: ..., // ミドルウェアの設定 //middleware: ... } </script> <style> .red { color: red; } </style>
メタタグ
-
<meta>
の内容はすべてnuxt.config.js
に定義できる- ページ単位でカスタムしたい場合はコンポーネントにheadプロパティを定義する
nuxt.config.jshead: { meta: [ { charset: 'utf-8' }, ], link: [ { rel: 'stylesheet', href: 'https://fonts.googleapis.com/css?family=Roboto' } ] }
非同期データ処理
asyncDataとコンテキスト
コンポーネントの asyncData
プロパティ(メソッド)は、ページのロードとは非同期的なデータの読み込みのために用いる。
-
asyncDataが呼ばれるたびに、その結果がdataにマージされる
- サーバサイドでは、ページがリクエストされた際に一度だけ呼ばれる
- クライアントサイドでは、ページ遷移のたびに呼ばれる
-
asyncDataは
this
を使えない- コンポーネントがinstanciateされる前に、別のスコープで(非同期に)呼び出されるため
- 代わりに引数の
context
を介して必要なデータを取得できる
-
Promiseオブジェクトを返すほか、async/awaitを使って書くこともできる
// Promise export default { asyncData ({ params }) { return axios.get('https://...') .then((res) => { return { ... } }) } } // async/await export default { async asyncData ({ params }) { let { data } = await axios.get('...') return { title: data.title } } }
-
Promiseによってエラーの制御もできる
export default { asyncData ({ params, error }) { return axios.get('...') .then((res) => { return { ... } }) .catch((e) => { error({ statusCode: 404, message: 'Not Found' }) }) } }
Asset/Static
Asset
-
assets/
に配置されたファイルは vue-loader, file-loaderなどwebpackの機能を利用して「アセット」として参照できる-
アセットはvueファイルから、
~assets/...
の形式で参照できる<template> <img src="~/assets/image.png"> </template>
-
file-loaderの場合、アセットファイルはサーバ上にバージョン付きのファイル名で配置される
-
url-loaderの場合、アセットファイル(画像)はURL-encodingされてHTML上にインライン展開される
-
Static
-
static/
に配置されたファイルは Assetの機能を利用することなく、単に静的なファイルとして配置・公開される- faviconなどはここに置く
Plugin
-
npmパッケージをNuxtで利用したい場合、インストールするだけでそのまま利用できる
$ npm install --save axios
<template> ... </template> <script> import axios from 'axios' export default { async asyncData ({ params }) { let { data } = await axios.get('...') // ... } } </script>
-
Vueのプラグインを利用したい場合、
plugins/
以下に設定を追加する必要があるplugins/some-vue-plugin.jsimport Vue from 'vue' import SomeVuePlugin from 'some-vue-plugin' Vue.use(SomeVuePlugin)
nuxt.config.jsexport default { // ... plugins: [ '~/plugins/some-vue-plugin' // クライアント/サーバサイドにそれぞれ限定のプラグインはモードを指定できる { src: '~/plugins/some-client-only-plugin', mode: 'client' } ] // プラグインがES6などで書かれている場合はビルドの指定も必要になる build: { transpile: ['some-vue-plugin'] } }
Module
-
Module = Nuxt自体の機能拡張
- 例:
-
@nuxtjs/axios
: Nuxtとaxiosの統合 -
@nuxtjs/auth
: 認証機能を提供する
-
- 例:
-
Moduleはnpmパッケージとして公開するほか、プロジェクトローカルに独自定義することもできる
modules/some-module.jsexport default function SomeModule(options){ // ... }
ビルド/デプロイ
-
NuxtはCLIを提供しており、これによってビルドやデプロイができる
package.json{ // ... // グローバルインストールした場合は $ nuxt で直接呼べる // ローカルインストールした状態で利用したい場合はpackage.jsonにscriptを設定する // $ npm run dev などとして利用可能 "scripts": { "dev": "nuxt", "build": "nuxt build", "start": "nuxt start", "generate": "nuxt generate", "test": "jest" }, }
-
Appの提供形式によって利用するコマンドが変わってくる
- 開発環境では
nuxt
でサーバを起動する - SSRの場合は
nuxt start
によって本番モードでサーバを起動する - 静的サイトの場合は
nuxt generate
でページをビルドする - SPAの場合も同様に
nuxt generate
でビルドする(SPAモード指定が必要)
- 開発環境では