はじめに
この記事は、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です。
※ 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.js
はvue-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を利用して、
header
とattribute
を更新ができる
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を利用して、オブジェクトのキャッシュができる
module.exports = {
cache: true
}
Custom Loading
- デフォルトの
progress bar
をカスタマイズできる - 自分で作成した
loading component
をデフォルトの代わりに設定できる
module.exports = {
loading: 'components/loading.vue'
}
Custom Routes
- Routingで見てきた以外に、ルーティングを独自に設定できる
module.exports = {
router: {
routes: [
{ name: 'user', path: '/users/:id(\\d+)', component: 'pages/_user' }
]
},
build: {
vendor: ['axios']
}
}
Global CSS
- 以下の形式でグローバルCSSを設定できる
- 外部モジュール
- cssへのコンパイルが必要な外部モジュール
- 内部ファイル
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
でグローバルなレイアウトを設定できる
<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
として設定
module.exports = {
build: {
vendor: ['axios', 'mini-toastr', 'vue-notifications']
},
plugins: [
'~plugins/vue-notifications.js'
]
}
Routes transitions
- トランジション効果の設定ができる
- 詳しくはVue.jsのドキュメントトランジション効果 - vue.jsを参照
Async Datas
- Promise
- callback
を利用した非同期通信の書き方の紹介
Vuex Store
- Vuexを使ってStateパターンを実装
-
/store
フォルダ配下にファイルを設置していく
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
を利用してテストが書ける。
/*
** 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をフォローして、ぜひこれから注目していきましょう!