Nuxt: npm install からMySql-DBとの接続まで

March 7, 2020 – 3:24 pm

Webアプリケーション作成用のフレームワークのNUXTJSに興味を持った。

このフレームワークの枠組みについて一通り理解するために、我がLinuxサーバ上にこれをインストールし、MySQL DBにアクセスし、DB上のデータをWeb上に描画するまでを実際にやってみた。

作業内容について比較的詳細にメモしておいた。

NUXTのインストールと初期設定
node, npm のversion:

$ node -v
v10.16.3
$ npm -v
6.14.2

Nuxt の npm install

$ cd sample-app
$ npm init -y
$ npm install nuxt --save
npm WARN deprecated core-js@2.6.11: core-js@<3 is no longer maintained and not recommended for usage due to the number of issues. Please, upgrade your dependencies to the actual version of core-js@3.

> core-js@2.6.11 postinstall /home/node/nuxt_trial/trial-app/node_modules/core-js
> node -e "try{require('./postinstall')}catch(e){}"

Thank you for using core-js ( https://github.com/zloirock/core-js ) for polyfilling JavaScript standard library!

The project needs your help! Please consider supporting of core-js on Open Collective or Patreon: 
> https://opencollective.com/core-js 
> https://www.patreon.com/zloirock 

Also, the author of core-js ( https://github.com/zloirock ) is looking for a good job -)


> ejs@2.7.4 postinstall /home/node/nuxt_trial/trial-app/node_modules/ejs
> node ./postinstall.js

Thank you for installing EJS: built with the Jake JavaScript build tool (https://jakejs.com/)


> nuxt@2.11.0 postinstall /home/node/nuxt_trial/trial-app/node_modules/nuxt
> opencollective || exit 0

                                                             
                                     :-:                     
                                   .==-+:                    
                                  .==. :+- .-=-              
                                 .==.   :==++-+=.            
                                :==.     -**: :+=.           
                               :+-      :*+++. .++.          
                              :+-      -*= .++: .=+.         
                             -+:      =*-   .+*: .=+:        
                            -+:     .=*-     .=*-  =+:       
                          .==:     .+*:        -*-  -+-      
                         .=+:.....:+*-.........:=*=..=*-     
                         .-=------=++============++====:     
                                         
                         Thanks for installing nuxtjs �
                 lease consider donating to our open collective
                        to help us maintain this package.                                         

      (省 略)

+ nuxt@2.11.0
added 1064 packages from 490 contributors and audited 10035 packages in 39.18s

found 0 vulnerabilities

package.json の編集

package.json:

{
  "name": "sample-app",
  "version": "1.0.0",
  "config": {
    "nuxt": {
       "host": "0.0.0.0",
       "port": "8080"
    }
  },
  "scripts": {
    "dev": "nuxt"
  },
  "dependencies": {
    "nuxt": "^2.11.0"
  }
}

Nuxt の標準的な Directory を構成:
Directory の確保:

$ mkdir assets components layouts middleware pages plugins static store

Directory 構成と 最小限のファイルの作成・配置:


  sample-app  --+- package.json
                +- nuxt.config.json
                +- assets       
                +- components  -- Logo.vue
                +- layouts     -- default.vue
                +- middleware    
                +- pages       -- index.vue
                               -- about.vue
                +- plugins
                +- static      -- favicon.ico
                +- store

/components/Logo.vue:

<template>
  <svg class="NuxtLogo" width="245" height="180" viewBox="0 0 452 342" xmlns="http://www.w3.org/2000/svg">
    <g fill="none" fill-rule="evenodd">
      <path
        d="M139 330l-1-2c-2-4-2-8-1-13H29L189 31l67 121 22-16-67-121c-1-2-9-14-22-14-6 0-15 2-22 15L5 303c-1 3-8 16-2 27 4 6 10 12 24 12h136c-14 0-21-6-24-12z"
        fill="#00C58E"
      />
      <path
        d="M447 304L317 70c-2-2-9-15-22-15-6 0-15 3-22 15l-17 28v54l39-67 129 230h-49a23 23 0 0 1-2 14l-1 1c-6 11-21 12-23 12h76c3 0 17-1 24-12 3-5 5-14-2-26z"
        fill="#108775"
      />
      <path
        d="M376 330v-1l1-2c1-4 2-8 1-12l-4-12-102-178-15-27h-1l-15 27-102 178-4 12a24 24 0 0 0 2 15c4 6 10 12 24 12h190c3 0 18-1 25-12zM256 152l93 163H163l93-163z"
        fill="#2F495E"
        fill-rule="nonzero"
      />
    </g>
  </svg>
</template>

<style>
.NuxtLogo {
  animation: 1s appear;
  margin: auto;
}

@keyframes appear {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}
</style>

/layouts/default.vue:

<template>
  <div>
    <nuxt />
  </div>
</template>

<script>
</script>

<style>
html {
  font-family: 'Source Sans Pro', -apple-system, BlinkMacSystemFont, 'Segoe UI',
    Roboto, 'Helvetica Neue', Arial, sans-serif;
  font-size: 16px;
  word-spacing: 1px;
  -ms-text-size-adjust: 100%;
  -webkit-text-size-adjust: 100%;
  -moz-osx-font-smoothing: grayscale;
  -webkit-font-smoothing: antialiased;
  box-sizing: border-box;
}

ブラウザ上への描画に必要なpages配下のテスト用vueファイルの作成・配置

/pages/index.vue:

<template>
<div class="container">
  <logo />
  <div>
    <h1>{{ title }}</h1>
    <Nuxt-Link to="/about">about</nuxt-link>
  </div>
</div>
</template>

<script>
import Logo from '~/components/Logo.vue'

export default {
  components: {
    Logo
  },
  data() {
    return {
      title: 'Sample-app'
    }
  }
}
</script>

<style>
.container {
   text-align: center;
   margin-top: 150px;
   font-size: 20px;
}
</style>

/pages/about.vue:

<template>
   <div class="container">
     <logo />
     <h1>{{ title }}</h1>
     <Nuxt-Link to="/">Top</Nuxt-Link>
   </div>
</template>

<script>
import Logo from '~/components/Logo.vue'

export default {
  components: {
    Logo
  },
  data() {
    return {
      title: 'about'
    }
  }
}
</script>

<style>
.container {
   text-align: center;
   margin-top: 150px;
   font-size: 20px;
}
</style>

ブラウザへの描画 実行:

実行コマンド コンソール出力部

$ npm run dev

> sample-app@1.0.0 dev /home/user01/sample-app
> nuxt

   ╭─────────────────────────-
   │                                               │
   │   Nuxt.js v2.11.0                             │
   │   Running in development mode (universal)     │
   │                                               │
   │   Listening on: http://192.168.11.111:8080/   │
   │                                               │
   ╰──────────────────────────

ℹ Preparing project for development                                           
ℹ Initial build may take a while                                        
✔ Builder initialized                                                        
✔ Nuxt files generated                                                                

✔ Client
  Compiled successfully in 5.08s

✔ Server
  Compiled successfully in 3.12s

ℹ Waiting for file changes                                                             
ℹ Memory usage: 171 MB (RSS: 230 MB) 

apache virtual hosts関連部 (ブラウザに出力)
/etc/httpd/conf.d/vhost.conf:

<VirtualHost *:80>
     ServerName node.yamasnet.com
     RewriteEngine On
     RewriteCond %{HTTPS} off
     RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</VirtualHost>

<VirtualHost *:443>
    ServerName node.yamasnet.com
    ServerAdmin webmaster@yamasnet.com
    DocumentRoot /var/www/node

    ProxyRequests Off
    ProxyVia Off

    RewriteEngine On
    RewriteCond %{REQUEST_URI}  ^/socket.io            [NC]
    RewriteCond %{QUERY_STRING} transport=websocket    [NC]
    RewriteRule /(.*)           ws://localhost:8080/$1 [P,L]
    <Proxy *>       Require all granted
    </Proxy>
    proxyPass / http://localhost:8080/
    ProxyPassReverse / http://localhost:8080/

     SSLEngine on
     SSLHonorCipherOrder on
     Header set Strict-Transport-Security "max-age=31536000; includeSubDomains"
     SSLProtocol -All +TLSv1 +TLSv1.1 +TLSv1.2
     SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5
     SSLCertificateFile /etc/letsencrypt/live/yamasnet.com/cert.pem
     SSLCertificateKeyFile /etc/letsencrypt/live/yamasnet.com/privkey.pem
     SSLCertificateChainFile /etc/letsencrypt/live/yamasnet.com/chain.pem

     Protocols h2 http/1.1
</VirtualHost>

ブラウザへの出力:

Top-page(index.vueに対応)

Top-page(index.vueに対応)

npm パッケージの取り込み(パッケージ momentを例に)

package moment の npm install:

$ npm install moment --save

/pages/index.vue:

<template>
<div class="container">
  <logo />
  <div>
    <h1>{{ title }}</h1>
    <Nuxt-Link to="/about">about</nuxt-link>
    <p> now: {{ now }} </p>
  </div>
</div>
</template>

<script>
import Logo from '~/components/Logo.vue'
import moment from 'moment'

export default {
  components: {
    Logo
  },
  data() {
    return {
      title: 'Sample-app'
    }
  },
  computed: {
    now() {
       let strfmt ='YYYY-MM-DD HH:mm:ss dddd'
       return moment().format(strfmt)
    }
  },
}
</script>

<style>
.container {
   text-align: center;
   margin-top: 150px;
   font-size: 20px;
}
</style>

Top-page(index.vueに対応) momentを取り込み時刻を出力

MySQL DBとの接続

npm パッケージ express, axios, mysqlをインストール

$ npm install express axios mysql --save
npm WARN sample-app@1.0.0 No description
npm WARN sample-app@1.0.0 No repository field.
npm WARN sample-app@1.0.0 No license field.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.1.2 (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.1.2: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.11 (node_modules/watchpack/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.11: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})

+ axios@0.19.2
+ mysql@2.18.1
+ express@4.17.1

package.json:

{
  "name": "sample-app",
  "version": "1.0.0",
  "config": {
    "nuxt": {      "host": "0.0.0.0",      "port": "8080"
    }
  },
  "scripts": {
    "dev": "nuxt"
  },
  "dependencies": {
    "axios": "^0.19.2",
    "express": "^4.17.1",
    "moment": "^2.24.0",
    "mysql": "^2.18.1",
    "nuxt": "^2.11.0"
  }
}

外部APIをたてる

外部API用ディレクトリ serverの確保し、そこにapi.jsを作成

$ mkdir server
$ vi api.js

api.js:

const express = require('express')
const app     = express()

module.exports = {
      path:    '/server',
      handler: app
}

app.get('/hello', (req, res) => {
    const mysql = require('mysql')
    const connection = mysql.createConnection({
       host  : 'localhost',
       user  : 'user',
       database: 'BookDB',
       password: 'password'
    })
    connection.connect()
    let sql ='select * from book_table'
    connection.query(sql, function(error, row, fields) {
      if (error) {
         console.log(error);
      }
      let dat = [];
      for (let i=0; i<row.length; i++) {
         dat.push({id: row[i].book_id, title: row[i].title, author: row[i].author})
      }
      ret = JSON.stringify(dat)
      res.send( ret )
    })
    connection.end()
})

上記 api.jsではMySQL DBのサンプル用に作成したBookDBをテストデータとして用いた。BookDBの内容については、MySQLを学習(3):INSERT文を用いたData入力フォーム作成参照

外部API(/server/api.js)をNUXTに取り込むためnuxt.config.jsにmoduleとして登録

nuxt.config.js:

module.exports = {
serverMiddleware:['~/server/api.js'],
}

/pages/index.vueをMySQL DBを受け取りブラウザ上に反映するよう修正

/pages/index.vue:

<template>
<div class="container">
  <logo />
  <div>
    <h1>{{ title }}</h1>
    <Nuxt-Link to="/about">about</nuxt-link>
    <p> now: {{ now }} </p>

    <ul>
     <li v-for="post in posts" :key=post.id>
         {{post.id}} {{post.title}} {{post.author}}
     </li>
    </ul>

  </div>
</div>
</template>

<script>
import Logo from '~/components/Logo.vue'
import moment from 'moment'
import axios from 'axios'

export default {
  components: {
    Logo
  },
  data() {
    return {
      title: 'Sample-app',
      posts: []
    }
  },
  mounted() {
    axios.get('/server/hello')
         .then(response => this.posts = response.data)
  },
  computed: {
    now() {
       let strfmt ='YYYY-MM-DD HH:mm:ss dddd'
       return moment().format(strfmt)
    }
  },
}
</script>

<style>
.container {
   text-align: center;
   margin-top: 150px;
   font-size: 20px;
}
</style>

ブラウザへの描画・実行

$ npm run dev
  (以下 省略)

ブラウザへの出力:

Top-page(index.vueに対応)


Post a Comment