Nuxt.jsとOnsenUIでHello,Worldするまで







近頃Nuxt.jsというフレームワークが流行っているので触ってみることにしました

ついでにOnsenUIというUIコンポーネントを触ってみたいという思いがあったので、「Nuxt.jsでOnsenUIのHelloWorldをする」ことを試してみようかなと思ってやってみました

Nuxt.jsの位置づけ

Nuxt.jsがWebのアーキテクチャでいうところのどのレイヤの役割を持つんだろうか?というのが最初にわかりにくいところだったんですが、基本的には「MVCでいうところのViewとController」を薄くサポートするという認識です。

データベースとの接続を持ったりするいわゆるRailsで言うところの「Model層」はNuxtで書くべきではない認識です。

データベース通信部分はexpress+ORMで別途にAPIサーバを立て、nuxt側からはaxiosを使ってHTTP通信を使ってデータをフェッチする設計が良さそうです。

プロジェクト作成

nuxtのプロジェクトを作成します

vue init nuxt-community/starter-template nuxt-sandbox
cd nuxt-sandbox
yarn install

nuxt公式インストール手順

OnsenUIのVueComponentをnpmでインストール

OnsenUIとそのVueのライブラリをyarnでインストールします

yarn add onsenui vue-onsenui

OnsenUI公式のVueインストール手順

Componentを作成

Nuxt.jsでは、画面に紐付かない各種VueComponentは

{project_root}/components/

に配置するのがNuxt流

このディレクトリ以下に単一ファイルコンポーネントとして配置する

例えばcomponents/HelloWorld.vueを作成

<template>
    <p>Hello,World!</p>
</template>

<script>
  export default {
  }
</script>

<style scoped>

</style>


VueComponentの構造上、Wordpressに書きづらい…(scriptタグが勝手に吹っ飛んだりする)

Indexページを作成

各種ページのルートとなるコンポーネントは

{project_root}/pages/

に配置します。

pages/tasks/index.vue

を作成してみます


<template>
  <div>
    <v-ons-page>
      <v-ons-toolbar>
        <div class="center">Hello,OnsenUI!</div>
      </v-ons-toolbar>
      <HelloWorld></HelloWorld>

    </v-ons-page>
  </div>
</template>

<script>
  import HelloWorld from '@/components/HelloWorld.vue'
  // Webpack CSS import
  import 'onsenui/css/onsenui.css';
  import 'onsenui/css/onsen-css-components.css';
  import axios from 'axios'

  // JS import
  import Vue from 'vue';
  import VueOnsen from 'vue-onsenui'; // This already imports 'onsenui'

  Vue.use(VueOnsen);


  export default {
    name: "index",
    components: {
      HelloWorld
    }
  }
</script>

<style scoped>

</style>

このページにブラウザからアクセスするには、{host}/tasksにアクセスします。

Pluginを記述

OnsenUIのVueComponentを読み込むため、plugins/vue-onsenui.jsに以下を記述

// Webpack CSS import
import 'onsenui/css/onsenui.css';
import 'onsenui/css/onsen-css-components.css';

// JS import
import Vue from 'vue';
import VueOnsen from 'vue-onsenui'; // This already imports 'onsenui'

Vue.use(VueOnsen);

ハマりどころ

onsenui.jsでwindow is not definedエラー


  nuxt:render Rendering url /tasks +0ms
{ ReferenceError: window is not defined
    at /Users/yukitoohira/Documents/development/nuxt-sandbox/node_modules/onsenui/js/onsenui.js:35:16
    at /Users/yukitoohira/Documents/development/nuxt-sandbox/node_modules/onsenui/js/onsenui.js:41:2
    at onsElements (/Users/yukitoohira/Documents/development/nuxt-sandbox/node_modules/onsenui/js/onsenui.js:4:82)
    at Object.<anonymous> (/Users/yukitoohira/Documents/development/nuxt-sandbox/node_modules/onsenui/js/onsenui.js:7:2)
    at Module._compile (module.js:662:30)
    at Object.Module._extensions..js (module.js:673:10)
    at Module.load (module.js:575:32)
    at tryModuleLoad (module.js:515:12)
    at Function.Module._load (module.js:507:3)
    at Module.require (module.js:606:17)
    at require (internal/module.js:11:18)
    at /Users/yukitoohira/Documents/development/nuxt-sandbox/node_modules/vue-onsenui/dist/vue-onsenui.js:4:90
    at Object.<anonymous> (/Users/yukitoohira/Documents/development/nuxt-sandbox/node_modules/vue-onsenui/dist/vue-onsenui.js:7:2)
    at Module._compile (module.js:662:30)
    at Object.Module._extensions..js (module.js:673:10)
    at Module.load (module.js:575:32) statusCode: 500, name: 'ReferenceError' }

window または document が undefined のときは?

回避策:とりあえずspaモードで起動する

ライブラリの中のonsenui.jsでグローバル変数windowを読み込もうとしていますが、サーバーサイドレンダリングではwindow変数がないためエラーになってしまいます。

暫定的ですがSSRをdisableしてSPAモードで起動します。

起動時に-sオプションを付与することでSSRを使用せずに起動できます。

package.json

{
  "name": "nuxt-sandbox",
  "version": "1.0.0",
  "description": "Nuxt.js project",
  "author": "yukito ohira",
  "private": true,
  "scripts": {
    "dev": "nuxt -s",
    "build": "nuxt build",
    "start": "nuxt start",
    "generate": "nuxt generate",
    "lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
    "precommit": "npm run lint"
  },
  "dependencies": {
    "axios": "^0.18.0",
    "nuxt": "^1.0.0",
    "onsenui": "^2.10.4",
    "vue-onsenui": "^2.6.1"
  },
  "devDependencies": {
    "babel-eslint": "^8.2.1",
    "eslint": "^4.15.0",
    "eslint-friendly-formatter": "^3.0.0",
    "eslint-loader": "^1.7.1",
    "eslint-plugin-vue": "^4.0.0"
  }
}


localhost:3000/tasks に接続して動作確認

npm run dev

でNuxtサーバを起動、localhost:3000/tasksにアクセスします。

多少不格好ですがやりたいつなぎこみはちゃんと出来ているので良し

後編・Nuxtサーバと通信するバックエンドサーバを立ち上げる記事はこちら

nuxt.jsで作成したWebアプリのBackendサーバーをexpress+sequelizeで立てる