# Nuxt.js

# API

https://nuxtjs.org/api (opens new window)

# 方針を決める

Nuxt のプロダクション環境での使い方は 3 つある。

# Universal Mode(サーバあり)

  • mode: 'universal'
  • デプロイ方法 --- Node.js サーバにソースをクローンしyarn startする。サーバが必要
  • 非同期データは、
    • 初回リクエスト時はサーバ側で取得する(常に最新)
    • ページ遷移時など、2 回目以降はクライアント側で取得する

# Universal Mode(サーバなし)

  • mode: 'universal'
  • デプロイ方法 --- nuxt generateで生成された静的ファイルを単に配布する。サーバが不要
  • 非同期データは、
    • 初回リクエスト時は、ビルド時に取得したデータで固定される(=疑似的な SSR と考えればよい)。このため、動的データに変更があったときは再ビルド・再デプロイが自動で行われるフローを構築するなどの処置が必要となる。
    • ページ遷移時など、2 回目以降はクライアント側で取得する

# SPA Mode

  • mode: 'spa'
  • デプロイ方法 --- nuxt generateで生成された静的ファイルを単に配布する。サーバが不要
  • 非同期データは常にクライアント側で取得する

# インストール

# create-nuxt-app を使う

yarn global add create-nuxt-app
create-nuxt-app some-app
cd some-app
yarn dev

# 自前で作る

package.json

{
  "name": "my-app",
  "scripts": {
    "dev": "nuxt"
  },
  "dependencies": {
    "nuxt": "^2.0.0"
  }
}

pages/index.vue

<template>
  <h1>Hello world!</h1>
</template>
yarn
yarn dev

# Directory Structure

# Directories

# assets

  • webpack でコンパイルされるべき Less, Sass, Javascript ファイルなどを格納する

# components

  • Vue コンポーネントを格納する
  • Nuxt.js は components ディレクトリ内のコンポーネントの data メソッドについては手を加えない
  • 一方、Nuxt.js は pages ディレクトリ内のコンポーネントの data メソッドには非同期データを扱えるよう手を加える

# layouts

  • アプリケーションのレイアウトファイルを格納する。

# middleware

  • ミドルウェアを格納する
  • ミドルウェアは、ページやレイアウトをレンダリングする前に動作するファンクションである。

# pages

  • .vueファイルを格納する。ここに配置したファイルが、View と Routes になる。

# plugins

  • root Vue.js Application が動きはじめる前に動作させたいプラグインを格納する

# static

  • 静的ファイルを格納する。
  • ここに置いたファイルは webpack を経由せず、そのまま/に配置される

# store

  • Vuex 関連のファイルを格納する

# nuxt.config.js

  • nuxt.js のコンフィグファイル

# Aliases

  • ~or@srcDirを指す
  • ~~or@@rootDirを指す

デフォルトでは srcDir と rootDir は同じ

vue テンプレートでファイルを相対指定する時に、次のように使う

~/assets/your_image.png
~/static/your_image.png

# Configuration

API ドキュメント (opens new window)

# 設定項目

# build

  • webpack 関連の設定を行う
    • 例えば、webpack のvendor.bundle.jsに入れ込むモジュールを指定する。これにより本体 bundle の容量を減らすことができる。

# css

グローバルに使用する CSS を指定する。

# dev

development or productionモードを指定する。

# env

環境変数を指定する。環境変数はサーバサイド、クライアントサイドの両方から参照できる。

# generate

nuxt generate(Static Generated Deployment)した時、動的なルーティングは無視される。 動的なルーティングも含めて静的な HTML ファイルに変換したいときは、ここに設定を記述する。

デフォルトの meta タグを指定する

# loading

ローディング中に表示するコンポーネントを指定する

# modules

nuxt で使用するモジュールを指定する。モジュール= nuxt の設定を一括して行うプラグインのようなもの

# modulesDir

node_modulesフォルダの場所を指定する。

yarn の workspaces 機能を使っているなら、下記の設定が必須。

// 例えば`<projectRoot>/packages/nuxt`にnuxtプロジェクトを格納している場合
modulesDir: ['../../node_modules'],

# plugins

root Vue.js Application を開始する前に動作させたいプラグインを指定する。

# rootDir

nuxt のルートディレクトリを指定する

# server

ポート番号、IP、証明書の場所など、サーバのセットアップに関する情報を指定する。

# router

vue-router の設定を指定する。

# srcDir

ソースディレクトリを指定する。

# transition

ページのトランジションを指定する。

# Routing

# Routes

  • ファイル名がindex.vueだと、パスは''(ホーム)になる
  • フォルダ名 or ファイル名に_をつけると Dynamic Route(:idなど) になる
  • フォルダ内の_ファイルは一つまで。2 つ以上あると名前順で一番上のものが採用される
  • フォルダ内にindex.vueが存在しない場合、_から始まるファイルは任意のDynamic Route になる(index.vue の役割を兼ねる)
  • Dynamic Routes はnuxt generageコマンドでは無視される
pages/
--| category/
-----| _id.vue
--| users/
-----| _id.vue
-----| index.vue
--| index.vue
routes = [
  {
    name: 'index',
    path: '/',
    component: 'pages/index.vue',
  },
  {
    name: 'category-id',
    path: '/category/:id?',
    component: 'pages/category/_id.vue',
  },
  {
    name: 'users',
    path: '/users',
    component: 'pages/users/index.vue',
  },
  {
    name: 'users-id',
    path: '/users/:id',
    component: 'pages/users/_id.vue',
  },
];

# Nested Routes

  • ネストした Routes を定義するには、フォルダ名と同名の vue ファイルを作成する
pages/
--| users/
-----| _id.vue
-----| index.vue
--| users.vue
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',
      },
    ],
  },
];

# Dynamic Nested Routes

Dynamic Routes をネストさせることもできる。

pages/
--| _category/
-----| _subCategory/
--------| _id.vue
--------| index.vue
-----| _subCategory.vue
-----| index.vue
--| _category.vue
--| index.vue
routes = [
  {
    path: '/',
    component: 'pages/index.vue',
    name: 'index',
  },
  {
    path: '/:category',
    component: 'pages/_category.vue',
    children: [
      {
        path: '',
        component: 'pages/_category/index.vue',
        name: 'category',
      },
      {
        path: ':subCategory',
        component: 'pages/_category/_subCategory.vue',
        children: [
          {
            path: '',
            component: 'pages/_category/_subCategory/index.vue',
            name: 'category-subCategory',
          },
          {
            path: ':id',
            component: 'pages/_category/_subCategory/_id.vue',
            name: 'category-subCategory-id',
          },
        ],
      },
    ],
  },
];

# SPA fallback

TODO: よくわからない

Dynamic Routes で SPA フォールバックを有効にするには設定が必要らしい。ドキュメント (opens new window)参照。

# リンクの貼り方、子コンポーネントの配置の仕方

<!-- リンクを貼る router-linkは使えない-->
<nuxt-link to="/">Home page</nuxt-link>

<!-- 子コンポーネントの配置 router-viewは使えない -->
<nuxt-child />

# Vlidation

  • params のバリデーションを行うには、コンポーネントで次のようにする。
  • booblean か、boolean を解決する Promise を返すこと。
  • false だった場合は 404 ページ又は 500 ページが表示される。
export default {
  validate({ params }) {
    // Must be a number
    return /^\d+$/.test(params.id);
  },
};

# Transitions

# グローバルセッティング

/* assets/main.css */
.page-enter-active,
.page-leave-active {
  transition: opacity 0.5s;
}
.page-enter,
.page-leave-to {
  opacity: 0;
}
// nuxt.config.js
module.exports = {
  css: ['assets/main.css'],
};

# ページ単位のセッティング

/* assets/main.css */
.test-enter-active,
.test-leave-active {
  transition: opacity 0.5s;
}
.test-enter,
.test-leave-active {
  opacity: 0;
}
// コンポーネントで
export default {
  transition: 'test',
};

# Middleware

  • ページ(又はページグループ)をレンダリングする前になにかの処理を行うためのもの。
  • middlewareフォルダに配置する
  • ファイル名がミドルウェア名になる middleware/auth.js => auth
  • ミドルウェアは非同期にすることもできる。非同期にしたい場合は Promise を Return すること。

ミドルウェアはcontextを引数に取る。Context の詳細はこちら (opens new window)。context を書き換えたり、context にプロパティを追加することで、後にコンポーネントのasyncDatafetchで使えるようにする。

// middleware/auth.js
export default function(context) {
  context.userAgent = context.isServer
    ? context.req.headers['user-agent']
    : navigator.userAgent;
}

ミドルウェアは下記の順で実行される。

  1. nuxt.config.js
  2. マッチしたレイアウト
  3. マッチしたページ

ミドルウェアを使用するときは、nuxt.config.js、レイアウト、又はページに置いてmiddlewareキーを指定する。

// nuxt.config.jsの例
module.exports = {
  router: {
    middleware: 'auth',
  },
};

# Views

# Document

ルートディレクトリにapp.htmlを配置することでデフォルトの HTML テンプレートを上書きできる。 デフォルト設定は以下の通り。

<!DOCTYPE html>
<html {{ HTML_ATTRS }}>
  <head>
    {{ HEAD }}
  </head>
  <body {{ BODY_ATTRS }}>
    {{ APP }}
  </body>
</html>

# Layouts

layouts/default.vueを作成することで、デフォルトのレイアウトを上書きできる。 デフォルト設定は以下のとおり。

<template>
  <nuxt />
</template>

レイアウトファイルは下記の 3 パターンで作るのが鉄板。

  • default.vue(共通画面など。ヘッダ・フッタあり)
  • home.vue(トップページなど。全画面)
  • blank.vue(規約やお問い合わせ表示用の 1 カラム画面)

# Error Page

layouts/error.vueを作成することで、デフォルトのエラーページを上書きできる。 デフォルト設定はこちら (opens new window)

# Custom Layout

layoutsフォルダの第一階層においたファイルは、レイアウトとして登録される。登録したレイアウトは、コンポーネントで使用することができる。

例)layouts/blog.vue

<template>
  <div>
    <div>My blog navigation bar here</div>
    <nuxt />
  </div>
</template>

コンポーネント側でレイアウトを指定する

export default {
  layout: 'blog',
};

# Pages

Nuxt のページは、全て Vue コンポーネントである。 Nuxt は、このコンポーネントに特別なキーを追加して、アプリケーションの開発を容易にする。

// コンポーネント
export default {
  asyncData(context) {},
  fetch() {},
  head() {},
  // and more functionality to discover
};
キー名 説明
asyncData ページがインスタンス化される前に、データを取得し、dataにセットする。contextを引数として受け取る。
fetch ページがインスタンス化される前に、データを取得する。dataにセットするのではなく、storeを操作する時に使う。contextを引数として受け取る。
head 現在のページに対して<meta> タグを設定する。
layout layouts ディレクトリに定義されているレイアウトを指定する
loading loadingの状態を手動で処理する場合に使う。詳細はAPIドキュメント (opens new window)を参照。
transition ページの特定のトランジションを設定する
scrollToTop Boolean型(デフォルト値:false)で、ページをレンダリングする前にページを一番上にスクロールするかどうかを指定する。これはネストされたルートに使用される。
validate 動的なルーティングを行った際にparamsを検証する
middleware このページのミドルウェアを設定する
watchQuery どのクエリが変更された時に、上記のメソッド群を実行するか指定する(デフォルトではクエリ変更時に上記のメソッド群は実行されない)

# HTML Head

nuxt は head の管理にvue-metaを使用している。デフォルトの設定は以下の通り。

{
  keyName: 'head', // the component option name that vue-meta looks for meta info on.
  attribute: 'data-n-head', // the attribute name vue-meta adds to the tags it observes
  ssrAttribute: 'data-n-head-ssr', // the attribute name that lets vue-meta know that meta info has already been server-rendered
  tagIDKeyName: 'hid' // the property name that vue-meta uses to determine whether to overwrite or append a tag
}

アプリケーション単位、ページ単位で head プロパティを設定できる。

// グローバル設定(nuxt.config.js)の例
config = {
  head: {
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
    ],
    link: [
      {
        rel: 'stylesheet',
        href: 'https://fonts.googleapis.com/css?family=Roboto',
      },
    ],
  },
};

// ローカル設定の場合
export default {
  head() {
    return {
      script: [
        {
          src:
            'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js',
        },
      ],
      link: [
        {
          rel: 'stylesheet',
          href: 'https://fonts.googleapis.com/css?family=Roboto',
        },
      ],
    };
  },
};

親と子で重複させたくない項目については、hid(本家ではvmidと呼ばれている)キーを設定しておくことで子のほうが優先されるようになる。詳細はこちら (opens new window)

# Async Data

  • return したオブジェクトがdataにマージされる
  • Nuxt のモードにより、データ取得のタイミングが変わる
    • Universal Mode: 初回はサーバでデータ取得、以降はページ遷移時に Ajax で取得
    • Pre Rendered Mode: nuxt generate時にデータを取得して、あらかじめ HTML 化
    • SPA Mode: ページ遷移時に Ajax で取得
  • 第一引数にcontextを受け取る
  • store は使えない
  • thisでコンポーネントインスタンスにアクセスすることはできない(Instanciate する前だから)

実装の方法は次の 3 種類がある。実装例はこちら (opens new window)

  • Promise を返す
  • async/await を使う
  • callback を使う
// async/awaitの例
export default {
  async asyncData(context) {
    let { data } = await axios.get(`https://my-api/posts/${context.params.id}`);
    return { title: data.title };
  },
};

# 注意

query の変更ではasyncDataメソッド等は実行されない。実行したい場合はwatchQuery (opens new window)プロパティに下記のような設定を行う。

// 下記の設定により、'page'クエリが変更された時に、
// 全てのコンポーネントメソッド(asyncData, fetch, validate, layout, ...)が
// 実行されるようになる。
export default {
  watchQuery: ['page'],
};

# Context

context の詳細はこちら (opens new window)

context により、データ取得時に必要となる様々なデータを取得できる。例えば、_slug.vueコンポーネントにおいて params をする際は、context.params.slugで取得できる。

# エラーハンドリング

非同期データ取得に失敗したときのエラーは次のように処理する。

export default {
  asyncData({ params, error }) {
    return axios
      .get(`https://my-api/posts/${params.id}`)
      .then(res => {
        return { title: res.data.title };
      })
      .catch(e => {
        error({ statusCode: 404, message: 'Post not found' });
      });
  },
};

# Assets

# Assets(webpacked)

# 段階 1:vue-loader

nuxt は vue-loader を使用している。コンパイルの過程で、下記のような記述は依存モジュールとして変換される。

  • <img src="...">
  • background: url(...)
  • @import(CSS)

CSS の例: url('~/assets/image.png') => require('~/assets/image.png')

コンポーネントの例: <img src="~/assets/image.png"> => createElement('img', { attrs: { src: require('~/assets/image.png') }})

# 段階 2:file-loader, url-loader

その後、png のように、JavaScript ファイルでないものは、file-loaderurl-loaderを使って処理される。これらの利点は次の通り。

  • file-loader  ファイル名にハッシュを含めることでキャッシュをより良くする
  • url-loader  小さいファイルは base64 にして埋め込む。大きいファイルは file-loader にフォールバックする。

url-loader の初期設定

// 1kb以下のファイルはインライン化し、そうでないものは所定のフォルダに配置する
[
  {
    test: /\.(png|jpe?g|gif|svg)$/,
    loader: 'url-loader',
    query: {
      limit: 1000, // 1kB
      name: 'img/[name].[hash:7].[ext]',
    },
  },
  {
    test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
    loader: 'url-loader',
    query: {
      limit: 1000, // 1kB
      name: 'fonts/[name].[hash:7].[ext]',
    },
  },
];

# まとめ

最終的に、下記のような形になる。

<img src="~/assets/image.png" />
<!-- 上記は下記に変換される -->
<img src="/_nuxt/img/image.0c61159.png" /><!-- もしくはbase64インライン -->

# Static

robotx.txt など、webpack に触れさせたくないファイルは、staticフォルダに置くことで、そのままルートに配置される。

<!-- Static フォルダのファイルを使うときの記法 -->
<img src="/my-image.png" />

<!-- Assets(webpacked)フォルダのファイルを使うときの記法 -->
<img src="~/assets/my-image-2.png" />

# Plugins

  • root Vue.js インスタンスが開始する前に行っておきたい処理を Plugins に記載する。
  • 注意:Nuxt では、beforeCreatecreatedのみ、サーバ・クライアントサイドの両方で動作する。それ以外はクライアントサイドでしか動作しない。

# 外部パッケージの利用

例えばaxiosを使いたい場合

yarn add axios
// コンポーネントで
import axios from 'axios';

これだけでは、axiosがシングルトンにならず、容量が肥大化する。それを防ぐために、nuxt.config.jsに下記を記載する。

module.exports = {
  build: {
    vendor: ['axios'],
  },
};

# Vue Plugins

Vue のプラグインを使うには下記のようにする。

// plugins/vue-notifications.js:
import Vue from 'vue';
import VueNotifications from 'vue-notifications';

Vue.use(VueNotifications);

// nuxt.config.js
module.exports = {
  plugins: ['~/plugins/vue-notifications'],
};

デフォルトでは、プラグインは Webpack の App Bundle にバンドルされるので、Vendor Bundle にバンドルされるよう、次の一文を追加する。

// nuxt.config.js
module.exports = {
  build: {
    vendor: ['vue-notifications'],
  },
};

# $root や context へのインジェクト

  • アプリケーションワイドで使いたいファンクションは、$root(クライアントサイド、Vue.js のルートインスタンス)やcontext(サーバサイド)にインジェクトするとよい。
  • これらのファンクションには慣習として、$を頭につける。

# クライアントサイド(Vue インスタンスへのインジェクト)

// plugins/vue-inject.js
import Vue from 'vue';
Vue.prototype.$myInjectedFunction = string =>
  console.log('This is an example', string);

// nuxt.config.js
module.exports = {
  plugins: ['~/plugins/vue-inject.js'],
};

// Componentでの呼び出し方
export default {
  mounted() {
    this.$myInjectedFunction('test');
  },
};

# サーバサイド(context へのインジェクト)

// plugins/ctx-inject.js
export default ({ app }, inject) => {
  // Set the function directly on the context.app object
  app.myInjectedFunction = string =>
    console.log('Okay, another function', string);
};

// nuxt.config.js
module.exports = {
  plugins: ['~/plugins/ctx-inject.js'],
};

// Componentでの呼び出し方
export default {
  asyncData(context){
    context.app.myInjectedFunction('ctx!')
  }
}

# クライアントサイド・サーバサイドの両方にインジェクト

両方にいっぺんにインジェクトする方法。なお、ファンクション名の頭の$は自動的に付与される。

// plugins/cimbined-inject.js
export default ({ app }, inject) => {
  inject('myInjectedFunction', string => console.log('That was easy!', string));
};

// nuxt.config.js
module.exports = {
  plugins: ['~/plugins/combined-inject.js'],
};

// Componentでの呼び出し方
export default {
  mounted(){
      this.$myInjectedFunction('works in mounted')
  },
  asyncData(context){
    context.app.$myInjectedFunction('works with context')
  }
}

// storeでの呼び出し方
export const mutations = {
  changeSomeValue(state, newValue) {
    this.$myInjectedFunction('accessible in mutations')
  }
}
export const actions = {
  setSomeValueToWhatever (context)) {
    this.$myInjectedFunction('accessible in actions')
  }
}

# クライアントサイドでしか動かないプラグイン

クライアントサイドでしか動かないプラグインを使うときは、ssrfalseにする。

module.exports = {
  plugins: [{ src: '~/plugins/vue-notifications', ssr: false }],
};

# サーバサイドでしか動かないプラグイン

  • process.server 変数を使って制御する。この変数には、Webpack が server.bundle.js ファイルを作成するタイミングにおいてのみ true がセットされる。
  • nuxt generate コマンドによって生成されたアプリケーションの中にいるかどうか知る必要がある場合は、process.static 変数に true がセットされているかでチェックする。

# Module

Nuxt のセットアップを簡単にする方法。

// modules/simple.js
module.exports = function SimpleModule(moduleOptions) {
  this.options = {}; // 何らかの処理
  this.nuxt = {} // 何らかの処理
  this = {} // 何らかの処理
  // ...
};

// nuxt.config.js
module.exports = {
  modules: [
    // Simple usage
    '~/modules/simple',
    // Passing options
    ['~/modules/simple', { token: '123' }],
  ],
};
  • moduleOptions 上記で言うところの{ token: '123' }
  • this.options nuxt.config.js 自身を指す。書き換えても OK。
  • this.nuxt nuxt のインスタンス (opens new window)を指す
  • this モジュールのコンテキストを指す。Nuxt の設定を変更するメソッド類が用意されている。詳細 (opens new window)
  • module.exports.meta モジュールを npm で公開する時に設定する

# 使用例

# config ファイルを参照する

// nuxt.config.js
module.exports = {
  axios: {
    option1,
    option2,
  },
};

// module.js
module.exports = function(moduleOptions) {
  const options = Object.assign({}, this.options.axios, moduleOptions);
  // ...
};

# プラグインの追加

// plugin.js
import Vue from 'vue';
import BootstrapVue from 'bootstrap-vue/dist/bootstrap-vue.esm';
Vue.use(BootstrapVue);

// module.js
module.exports = function(moduleOptions) {
  // Register `plugin.js` template
  this.addPlugin(path.resolve(__dirname, 'plugin.js'));
};

# テンプレートプラグインの追加

TODO:よくわからない lodash templates を使っているらしい

// plugin.js
ga('create', '<%= options.ua %>', 'auto');

// module.js
module.exports = function nuxtBootstrapVue(moduleOptions) {
  this.addPlugin({
    src: path.resolve(__dirname, 'plugin.js'),
    options: {
      ua: 123,
    },
  });
};

# CSS ライブラリの追加

// module.js
module.exports = function(moduleOptions) {
  this.options.css.push('font-awesome/css/font-awesome.css');
};

# Emit Assets

webpack プラグインを登録する方法 TODO: よくわからない

module.exports = function(moduleOptions) {
  const info = 'Built by awesome module - 1.3 alpha on ' + Date.now();

  this.options.build.plugins.push({
    apply(compiler) {
      compiler.plugin('emit', (compilation, cb) => {
        // This will generate `.nuxt/dist/info.txt' with contents of info variable.
        // Source can be buffer too
        compilation.assets['info.txt'] = {
          source: () => info,
          size: () => info.length,
        };
        cb();
      });
    },
  });
};

# カスタムローダーを登録する

前項と同じことはextendBuildを使って実現することもできる。

module.exports = function(moduleOptions) {
  this.extendBuild((config, { isClient, isServer }) => {
    // `.foo` Loader
    config.module.rules.push({
      test: /\.foo$/,
      use: [
        /*something*/
      ],
    });

    // Customize existing loaders
    const barLoader = config.module.rules.find(
      rule => rule.loader === 'bar-loader',
    );
  });
};

# Nuxt の各段階で所定の処理を行う

// module.js
module.exports = function() {
  // Add hook for modules
  this.nuxt.hook('module', moduleContainer => {
    // This will be called when all modules finished loading
  });

  // Add hook for renderer
  this.nuxt.hook('renderer', renderer => {
    // This will be called when renderer was created
  });

  // Add hook for build
  this.nuxt.hook('build', async builder => {
    // This will be called once when builder created

    // We can even register internal hooks here
    builder.hook('compile', ({ compiler }) => {
      // This will be run just before webpack compiler starts
    });
  });

  // Add hook for generate
  this.nuxt.hook('generate', async generator => {
    // This will be called when a Nuxt generate starts
  });
};

# Vuex Store

# セットアップ

store ディレクトリにファイルがあれば、自動的に下記の処理が行われる。

  1. Vuex のインポート
  2. Vuex を Vendor Bundle に組み込み
  3. root Vue インスタンスに store オプションを追加(配下の全てのコンポーネントで利用できるように)

Nuxt には 2 つのモードがある。

  • Classic store/index.jsが store インスタンスを返すモード
  • Modules store フォルダにある各.jsファイルが Namespaced Module に変換される

# Classic Mode

ストアを返すファンクションをエクスポートすること。

// store/index.js
import Vuex from 'vuex';

const createStore = () => {
  return new Vuex.Store({
    state: {
      counter: 0,
    },
    mutations: {
      increment(state) {
        state.counter++;
      },
    },
  });
};

export default createStore;

# Modules Mode

このモードで使いたいときは次のようにする。

  • state はファンクションとして名前付きでエクスポート
  • mutations、actions、plugins 等は名前付き Object としてエクスポート
// store/index.js
export const state = () => ({
  counter: 0,
});
export const mutations = {
  increment(state) {
    state.counter++;
  },
};
export const plugins = [ myPlugin ]

// store/todos.js(サブフォルダにする必要はない)
export const state = () => ({
  list: []
})

export const mutations = {
  add (state, text) {
    state.list.push({
      text: text,
      done: false
    })
  },
  remove (state, { todo }) {
    state.list.splice(state.list.indexOf(todo), 1)
  },
  toggle (state, todo) {
    todo.done = !todo.done
  }
}

# nuxtServerInit

  • ルートストアの Actions でnuxtServerInitが定義されていると、Nuxt はそのアクションを呼び出す(サーバサイドのみ)。
  • 第二引数にcontextを取る。
actions: {
  nuxtServerInit ({ commit }, { req }) {
    if (req.session.user) {
      commit('user', req.session.user)
    }
  }
}

# Strict Mode

Strict モードを有効にしたいときは下記のようにする。

// Classic Mode
const createStore = () => {
  return new Vuex.Store({
    strict: false,
  });
};

// Module Mode
export const strict = false;

# Commands and Deployment

# Commands

  • nuxt 開発用サーバを立ち上げる
  • nuxt build webpack でビルド
  • nuxt start build したファイルをサーブ
  • nuxt generate 全てのページを静的 HTML ファイルとして書き出し

オプション

  • -c コンフィグファイルを指定
  • -s SPA モードで立ち上げ(SSR を無効化)

# Production Deployment

# Server Rendered Deployment (Universal)

node.js を使ってサーブする方法

nuxt build
nuxt start

# Static Generated Deployment (Pre Rendered)

yarn generate
# distフォルダをサーブする
  • デフォルトでは、このモードでは Dynamic Routes は無視されるので、手動でのルート生成 (opens new window)が必要。
  • このモードはユーザ認証を使うようなアプリケーションには向かない

# Single Page Application Deployment (SPA)

  • nuxt.config.jsmodespaにセットする
  • yarn build
  • distフォルダをサーブする

# Deployment Tools

# E2E Testing

こちら (opens new window))を参照

# ESLint と Prettier

こちら (opens new window)を参照してセットアップする。

# その他

# sass を使う

yarn add node-sass sass-loader
// nuxt.config.js
module.exports = {
  css: [
    // node モジュールを直接ロードする (ここでは SASS ファイル)
    'bulma',
    // プロジェクト内の CSS ファイル
    '~/assets/css/main.css',
    // プロジェクト内の SCSS ファイル
    '~/assets/css/main.scss',
  ],
};