234
212

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

はじめに

この記事は、Vue.js Advent Calendar 2016 12日目の代打記事です。

Nuxt.jsとは?

Few hours after the announcement of Next.js, the idea of creating server-rendered Vue.js applications the same way as Next.js became inevitable: Nuxt.js was born.

Next.jsのVue.js版。

特徴としては以下の点が挙げられている。

  • No need to write Webpack/Babel configuration
  • No need to create a node.js server
  • Writing *.vue files, because it rocks
  • Creating new routes by adding a file in the pages/ directory
  • Accessing the server data inside the routes components easily
  • Webpack/Babelの設定書く必要なし
  • node.jsサーバを準備する必要なし
  • *.vueファイルを書くだけでOK
  • pagesディレクトリにファイル追加すると自動ルーティング
  • ルートコンポーネント内のサーバデータに簡単アクセス

アプリケーション作成

公式ドキュメント: Installation

まずvue-cliをインストールしていない場合は、グローバルオプションでインストールしてください。

$ npm install -g vue-cli

プロジェクト名は[nuxt-example]としましょう。

$ vue init nuxt/starter nuxt-example
$ cd nuxt-example
$ npm install # or $ yarn
$ npm run dev

http://localhost:3000 にこのような画面が表示されていればOKです。

スクリーンショット 2016-12-18 3.27.43.png

vue-cliを使わない場合は、Installation「Starting from scratch」を参照

ディレクトリ構成

公式ドキュメント: Directory Structure

ミニマム構成

|-- pages
    |-- index.vue
|-- package.json
  • /pagesフォルダにindex.vueがありさえすればOK
  • index.vueがアプリケーションのルート(/)にルーティング
  • Hello-Worldサンプルが参考に

推奨構成

|--- assets
    |--- global.css
|--- components
    |--- nav.vue
|--- pages
    |--- index.vue
|--- plugins
    |--- filters.js
|--- static
    |--- favicon.ico
|--- store
    |--- index.js
|--- nuxt.config.js
|--- package.json
  • /storeフォルダを作成することで、Vuexが利用可能

エイリアス

ALIAS DIRECTORY
~ /
~assets /assets
~components /components
~pages /pages
~plugins /plugins
~static /static
~store /store

このエイリアスを利用することで、以下のように記述できる。

<img src="~static/img/logo.png" alt="Logo"/>

ルーティング

公式ドキュメント: Routing

  • Nuxt.jsvue-routerを利用
  • pagesフォルダに従って、ルーティングを作成

基本

このディレクトリ構成からは、次のようなvue-routerの設定が作られる。

|-- pages
    |-- posts
        |-- index.vue
        |-- welcome.vue
    |-- about.vue
    |-- index.vue
routes: [
  {
    path: '/posts',
    component: '~pages/posts/index.vue'
  },
  {
    path: '/posts/welcome',
    component: '~pages/posts/welcome.vue'
  },  
  {
    path: '/about',
    component: '~pages/about.vue'
  },
  {
    path: '/',
    component: '~pages/index.vue'
  }
]

応用

_プレフィックスを与えることで、Nuxt.jsのルーティングシステムに検知されないファイルを作成可能。

|-- pages
    |-- _about.vue
    |-- index.vue
routes: [
  {
    path: '/',
    component: '~pages/index.vue'
  }
]

サンプル集

2016/12/18時点では、ドキュメントには以上の項目しか用意されてない。
用意されているEXAMPLESから、Nuxt.jsでなにができるかを見ていきましょう。

SEO HTML Head

  • vue-metaを利用して、headerattributeを更新ができる
nuxt.config.js
module.exports = {
  head: {
    titleTemplate: '%s - Nuxt.js',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: 'Meta description' }
    ]
  }
}

Cached Components

  • lru-cacheを利用して、オブジェクトのキャッシュができる
nuxt.config.js
module.exports = {
  cache: true
}

Custom Loading

  • デフォルトのprogress barをカスタマイズできる
  • 自分で作成したloading componentをデフォルトの代わりに設定できる
nuxt.config.js
module.exports = {
  loading: 'components/loading.vue'
}

Custom Routes

  • Routingで見てきた以外に、ルーティングを独自に設定できる
nuxt.config.js
module.exports = {
  router: {
    routes: [
      { name: 'user', path: '/users/:id(\\d+)', component: 'pages/_user' }
    ]
  },
  build: {
    vendor: ['axios']
  }
}

Global CSS

  • 以下の形式でグローバルCSSを設定できる
    • 外部モジュール
    • cssへのコンパイルが必要な外部モジュール
    • 内部ファイル
nuxt.config.js
const { resolve } = require('path')

module.exports = {
  css: [
    // Load a node.js module
    'hover.css/css/hover-min.css',
    // node.js module but we specify the lang
    { src: 'bulma', lang: 'sass' },
    // Css file in the project
    // It is important to give an absolute path
    resolve(__dirname, 'css/main.css')
  ]
}

Layouts

  • /layouts/app.vueでグローバルなレイアウトを設定できる
/layouts/app.vue
<template>
  <nuxt-container>
    <img src="logo.png"/>
    <nuxt/>
  </nuxt-container>
</template>

<style scoped>
img {
  position: fixed;
  top: 20px;
  right: 20px;
  z-index: 1000;
}
</style>

Plugins

  • build.vendorに利用する外部モジュールを指定
  • アプリケーションが起動する前に定義する必要があるものはpluginsとして設定
nuxt.config.js
module.exports = {
  build: {
    vendor: ['axios', 'mini-toastr', 'vue-notifications']
  },
  plugins: [
    '~plugins/vue-notifications.js'
  ]
}

Routes transitions

Async Datas

  • Promise
  • callback

を利用した非同期通信の書き方の紹介

Vuex Store

  • Vuexを使ってStateパターンを実装
  • /storeフォルダ配下にファイルを設置していく
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    counter: 0
  },
  mutations: {
    increment (state) {
      state.counter++
    }
  }
})

export default store

Testing

  • ava: テストフレームワーク
  • jsdom: DOMシミュレートライブラリ

を利用してテストが書ける。

index.test.js
/*
** Test with Ava can be written in ES6 \o/
*/
import test from 'ava'
import jsdom from 'jsdom'
import { createServer } from 'http'
import { resolve } from 'path'

let nuxt = null
let server = null

// Init nuxt.js and create server listening on localhost:4000
test.before('Init Nuxt.js', (t) => {
  const Nuxt = require('../../../')
  const options = {
    rootDir: resolve(__dirname, '..'),
    dev: false
  }
  nuxt = new Nuxt(options)
  return nuxt.build()
  .then(function () {
    server = createServer((req, res) => nuxt.render(req, res))
    server.listen(4000, 'localhost')
  })
})

/*
** Example of testing only the html
*/
test('Route / exits and render HTML', async t => {
  let context = {}
  const { html } = await nuxt.renderRoute('/', context)
  t.true(html.includes('<p class="red-color">Hello world!</p>'))
  t.is(context.nuxt.error, null)
  t.is(context.nuxt.data[0].name, 'world')
})

/*
** Example of testing via dom checking
*/
test('Route / exits and render HTML', async t => {
  const window = await nuxt.renderAndGetWindow(jsdom, 'http://localhost:4000/')
  const element = window.document.querySelector('.red-color')
  t.not(element, null)
  t.is(element.textContent, 'Hello world!')
  t.is(element.className, 'red-color')
  t.is(window.getComputedStyle(element).color, 'red')
})

// Close server and ask nuxt to stop listening to file changes
test.after('Closing server and nuxt.js', t => {
  server.close()
  nuxt.close()
})

Production deployment

  • next.js同様にnowの利用を推奨

あわせて読みたい

おわりに

Nuxt.jsはまだまだ発展途上のプロダクトですが、Vue.jsで開発する上でのデファクトスタンダードを学べるいい機会になると思いました。

Nuxt.jsをフォローして、ぜひこれから注目していきましょう!

234
212
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
234
212

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?