Getting started

何にせよはずは環境を整える所から初めましょうか。

npmコマンドでvue-cliをグローバルにインストールします。これでvueコマンドが使えるようになります。

$ npm i -g vue-cli

nuxtjsなプロジェクトを作るには、以下のようなvue init nuxt/starter <project name>コマンドを実行するだけです。 色々聞かれますが、全部Enterを押してれば大丈夫だと思います。 最後に出てきたTo get startedに書かれてることをそのまま実行します。

$ vue init nuxt/starter try-nuxt

# ? Project name try-nuxt
# ? Project description Nuxt.js project
# ? Author nju33 <nju33.ki@gmail.com>
#
#    vue-cli · Generated "try-nuxt".
#
#    To get started:
#
#      cd try-nuxt
#      npm install # Or yarn
#      npm run dev

これでだけでNuxtJSなプロジェクト環境ができました。

npm run devとするとlocalhost:3000でサーバーが立ち上がります。アクセスしてこんな画面になったら準備完了です。

After run dev

ちなみにポートを変えたい場合はdevスクリプトでPORT環境変数に違う数値を設定するように変更します。

{
  "scripts": {
    "dev": "PORT=3333 nuxt"
  }
}

Vue-cliで作成したNuxtJSなプロジェクトに用意されてるコマンドについて

Vue-cliで作成したNuxtJSなプロジェクトのpackage.jsonにいくらかscriptsに登録済みのコマンドがあると思います。 これらの意味は以下のようなになります。

  • nuxt / Develop環境でサーバー(with Hot-reloading)を建てます
  • nuxt build / Production環境でファイルをビルドする
  • nuxt start / Production環境でサーバーを建てる
  • nuxt generate / 静的サイトとして公開できるように実際に置く用のファイルを作成します

NuxtJSで生成されたファイルを眺める

NuxtJSのディレクトリ構造

表示はできたけど、中の構造がどうなってるのかさっぱり分からないので、見てみたいと思います。とりあえずファイル構造はこうなってますね。

.
├── README.md
├── .nuxt
│   ├── App.vue
│   ├── client.js
│   ├── components
│     ├── nuxt-child.js
│     ├── nuxt-error.vue
│     ├── nuxt-link.js
│     ├── nuxt-loading.vue
│     └── nuxt.vue
│   ├── index.js
│   ├── router.js
│   ├── server.js
│   └── utils.js
├── assets
│   ├── css
│     └── main.css
│   └── img
│       └── logo.png
├── components
│   └── Footer.vue
├── dist # Generateした本番用ファイル
├── layouts
│   ├── default.vue
│   └── error.vue
├── node_modules # 略
├── nuxt.config.js
├── package.json
├── pages
│   ├── about.vue
│   └── index.vue
├── static
│   └── favicon.ico
├── plugins # デフォルトでは無い(vue用のプラグインを使う)
├── store # デフォルトでは無い(vuexを使う)
└── yarn.lock # yarn の時だけ

NuxtJSでは、「ここにはこんなファイルを置く」というようなルールがあるので、見ていきます。

Pages

ここへはページとなりうる.vueファイルを起きます。ここに置いたファイルはNuxtJSで自動生成される.nuxt/components/nuxt-link.jsというコンポーネントを使うことでリンクを貼ることができます。


  About page

Layouts

layouts/へ置きます。初期ではlayouts/default.vuelayouts/error.vueがあります。

重要なのは<nuxt/>というコンポーネントでここに現在のメイン要素の内容が入ります。

新しいLayoutを追加したい時はここにnew.vueファイルを作るだけです。(newはただの例で名前はなんでもいい)そのLayoutを使いたい時は、Pageの Export Object のLayoutキーにnew(ファイル名)と設定します。

Assets

ここに置いたファイルは読み込む前にWebpackのLoaderの処理を適用することができます。

ちなみにLoaderで処理させるようにするためには、例えばpages/index.vueに含まれるような以下の部分

<img src="../assets/img/logo.png"/>

は、~を使ってこんな感じにする必要があります。

<img src="~assets/img/logo.png"/>

以下の設定はデフォルトの設定らしいです。

[
  {
    test: /\.(png|jpe?g|gif|svg)$/,
    loader: 'url-loader',
    query: {
      limit: 1000, // 1KO
      name: 'img/[name].[hash:7].[ext]'
    }
  },
  {
    test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
    loader: 'url-loader',
    query: {
      limit: 1000, // 1 KO
      name: 'fonts/[name].[hash:7].[ext]'
    }
  }
]

もし新しいLoaderを使いたいなどWebpackの設定を拡張したい場合は、nuxt.config.jsbuild.extend(config, {isDev, isClient})メソッドで行えます。例えば.lessを使いたい場合はこんな感じです。

build: {
  extend(config, {isDev, isClient}) {
    config.module.rules.push({
      test: /\.less$/,
      loader: 'less-loader'
    });
  }
}

Static

こっちはAssetsとほぼ一緒で、単にWebpackの処理をしないような静的ファイルを置きます。

Store

これは多分、複数のページに渡って状態を保持したい場合なんかに使うんじゃないかと思います。

この機能を使うには、vuexを追加でインストールする必要があります。

npm i -S vuex
yarn add vuex

NuxtJSはstore/index.jsファイルがあるとこれを実行してくれるので、このファイルでVuex.Storeのインスタンスをexportするようにします。

import Vuex from 'vuex';
export default new Vuex.Store({...});

exportしたstoreは、.vueファイルのTemplateの中で$storeという変数でアクセスできます。

<template>
  <button @click="$store.commit('increment')">{{$store.state.counter}}</button>
</template>

それぞれの値を分割exportしてNuxtJSにStoreを組み上げてもらう方法もあります。これはココを参照すると分かりやすいと思います。

Plugins

事前に使いたいVuePluginをインストールしておきます。(ここでは仮にvue-pluginとします)plugins/vue-plugin.jsを作って以下のようにします。

クライアントサイドだけで有効にしたい場合は、process.BROWSER_BUILD。サーバーサイドだけならprocess.SERVER_BUILDというフラグを使って有効なプラグインを変えることができます。。

import Vue from 'vue';
import VuePlugin from 'vue-plugin';

if (process.BROWSER_BUILD) {
  Vue.use(VuePlugin);
}

そして、nuxt.config.jsでそのプラグインを設定します。build.venderはパフォーマンスを上げるために指定します。

build: {vendor: ['vue-plugin']},
plugins: ['~plugins/vue-plugin']

Middleware

良くわからないので誰か教えてください。

ルーティングについて

「このPathnameなURLの時は、この.vueファイルで」みたいなことがnuxt.config.jsrouter.routesで設定できます。これは、VueRouterの設定と全く同じです。

router: {
  routes: [
    {
      name: 'index',
      path: '/',
      component: 'pages/index.vue'
    },
    {
      name: 'user',
      path: '/user',
      component: 'pages/user/index.vue'
    }
  ]
}

動的にルーティングしたい場合は、動的に変わる部分のディレクトリ名やファイル名に_をプレフィックスします。

router: {
  routes: [
    // ...
    {
      name: 'users-id',
      path: '/users/:id?',
      component: 'pages/users/_id.vue'
    },
    {
      name: 'slug',
      path: '/:slug',
      component: 'pages/_slug/index.vue'
    },
    {
      name: 'slug-comments',
      path: '/:slug/comments',
      component: 'pages/_slug/comments.vue'
    }
  ]
}

基準パスを設定するには親Routeにchildrenを設定します。上記のusers-idなRouteはこう書くこともできます。一つ重要な点は、childrenを持つようなcomponentはマークアップに<nuxt-child/>を書くということを忘れないようにする必要があります。

もし動的なパスの中にもIgnoreパターンを設定したい場合は、その.vueの Export Object の中にvalidateというメソッドを定義して弾くことができます。

validate() {
  export default {
    validate ({params}) {
      // Must be a number
      return /^\d+$/.test(params.id)
    }
  }  
}

上記では、params.idがNumberの時は正常に表示されますが、違う場合はerror.vueが表示されます。

router: {
  routes: [
    {
      path: '/users',
      component: 'pages/users.vue',
      children: [
        {
          path: '', // /users
          component: 'pages/users/index.vue',
          name: 'users'
        },
        {
          path: ':id', // /users/:id
          component: 'pages/users/_id.vue',
          name: 'users-id'
        }
      ]
    }
  ]
}

親が動的な場合にも対応できます。

router: {
  routes: [
    {
      path: '/:slug',
      component: 'pages/_slug.vue',
      children: [
        {
          path: ':childSlug', // /:slug/:childSlug
          component: 'pages/_slug/_childSlug.vue',
          chilren: [
            {
              path: '',
              component: 'page/_slug/_childSlug/index.vue'
              name: 'something'
            }
          ]
        }
      ]
    }
  ]
}

好きなパッケージを使う

基本的にただ<script/>の中でimportしたりして自由に使えるみたいです。ただし、パフォーマンスを上げるためにnuxt.config.jsbuild/venderに使ったパッケージ名を書いた方が良さげです。

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