Help us understand the problem. What is going on with this article?

Nuxt.js 入門

More than 3 years have passed since last update.

はじめに

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

Nuxt.jsとは?

https://nuxtjs.org/

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

https://github.com/nuxt/nuxt.js/tree/master/examples/head-elements

  • 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

https://github.com/nuxt/nuxt.js/tree/master/examples/cached-components

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

Custom Loading

https://github.com/nuxt/nuxt.js/tree/master/examples/custom-loading

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

Custom Routes

https://github.com/nuxt/nuxt.js/tree/master/examples/custom-routes

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

Global CSS

https://github.com/nuxt/nuxt.js/tree/master/examples/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

https://github.com/nuxt/nuxt.js/tree/master/examples/extend-app

  • /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

https://github.com/nuxt/nuxt.js/tree/master/examples/plugins-vendor

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

Routes transitions

https://github.com/nuxt/nuxt.js/tree/master/examples/routes-transitions

Async Datas

https://github.com/nuxt/nuxt.js/tree/master/examples/async-data

  • Promise
  • callback

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

Vuex Store

https://github.com/nuxt/nuxt.js/tree/master/examples/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

https://github.com/nuxt/nuxt.js/tree/master/examples/with-ava

  • 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をフォローして、ぜひこれから注目していきましょう!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした