Vue & Node.js開発環境構築 / サンプル・プログラム

--------------------------------------------------------------------------------

Vue & Node.js開発環境構築 / サンプル・プログラム

--------------------------------------------------------------------------------
・概要
  ・Node.jsでDataBaseからデータを入手するAPIを用意します。
    http://192.168.56.130:3000/api/list
    VueのスクリプトからこのAPIを呼び、フロント画面(Client画面)に
    表示します。
  ・Vue表示チェック
    http://192.168.56.130
    My IP-Address 192.168.56.130 <-- 読み替えて下さい。
--------------------------------------------------------------------------------

・前処理

 ・用意するもの

    CentOS-8.2.2004-x86_64-dvd1.iso

--------------------------------------------------------------------------------

・Oracle VM VirtualBox マネージャ で 新規作成

 ・名前    vue01
 ・タイプ   Linux
 ・バージョン Other Linux (64bit)

 ・メモリサイズ 1024MB
 ・仮想ハードディスクを作成する
 ・ハードディスクのファイルタイプ: VDI(VirtualBox Disk Image)
 ・物理ハードディスクにあるストレージ: 可変サイズ
 ・ファイルの場所とサイズ: vue01, 80GB
 ・[作成]

--------------------------------------------------------------------------------

・ストレージ

 ・CentOS-8.1.1911-x86_64-dvd1.iso

・ネットワーク
 ・固定IPの場合
  ・[設定(S)] - ネットワーク(固定IP)
   ・ブリッジ・アダプタ
   ・[OK]

 ・DHCPの場合
  ・[設定(S)] - ネットワーク(Local Only)
   ・NAT
   ・Host Only
   ・[OK]

--------------------------------------------------------------------------------

・インストール

 ・起動(T)
 ・Install CentOS 8
  ・Language: English (United States)
  ・DATE & TIME: Asia Tokyo
  ・KEYBOARD: Japanese
  ・SOFTWARE SELECTION: Minimal Install;
  ・KDUMP: disabled
  ・NETWORK & HOST ; Ethernet = ON; vue01.mydomain
  ・[Begin Installation]

  ・ROOT PASSWORD
  ・USER CREATION       // <-- devusr

  ・(処理終了を待つ)

  ・Reboot

  ・DHCPの場合(Local Only の場合)
      /etc/sysconfig/network-scripts/ifcfg-enp0s8
        ONBOOT=yes

  ・固定IPの場合
      $ su -
      # cd /etc/sysconfig/network-scripts
      # cp ifcfg-enp0s3 _ifcfg-enp0s3_org
      # vi ifcfg-enp0s3
      # diff _ifcfg-enp0s3_org ifcfg-enp0s3
      < BOOTPROTO="dhcp"
      ---
      > BOOTPROTO="static"
      > IPADDR="192.168.3.223"
      > NETMASK="255.255.255.0"
      > GATEWAY="192.168.3.1"
      #
      
      # vi /etc/resolv.conf
      # cat /etc/resolv.conf
      nameserver 192.168.3.1
      #

    ・SELinuxを無効にする。
      # vi /etc/selinux/config
      SELINUX=disabled

  ・Reboot
      # shutdown -r now

--------------------------------------------------------------------------------

・以降、client端末からsshでログインし、処理します。

--------------------------------------------------------------------------------

# yum -y update

###
### reboot
###
# shutdown -r now

###
### remi and PowerTools.
###
# yum -y install epel-release https://rpms.remirepo.net/enterprise/remi-release-8.rpm; \
yum config-manager --set-enabled PowerTools

###
### Tools
###
# yum -y install tar wget net-tools gcc make zip unzip emacs nkf; \
yum -y install ImageMagick ImageMagick-devel; \
yum -y install git

###
### .bashrc
###
# cd
# vi .bashrc
# cat .bashrc
<<<
# .bashrc

# User specific aliases and functions

# alias rm='rm -i'
# alias cp='cp -i'
# alias mv='mv -i'

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

alias ls='ls'
alias ll='ls -la'
alias e='emacs'
alias delb='rm -f *~ .??*~'
>>>

###
### .emacs
###
# cd
# vi .emacs
# cat .emacs
<<<
(setq-default tab-width 4 indent-tabs-mode nil)
>>>

###
### MariaDB
###
# yum -y install mariadb mariadb-server mariadb-devel

# systemctl enable mariadb.service; \
systemctl start mariadb.service

# mysql -u root -p
パスワード入力はCR(Enter)だけ。
MariaDB [(none)]> set password for 'root'@'localhost' = password('...password...');
MariaDB [(none)]> create database devdb character set utf8;
MariaDB [(none)]> create user 'devusr'@'localhost' identified by '...password...';
MariaDB [(none)]> grant all privileges on devdb.* to 'devusr'@'localhost';
MariaDB [(none)]> exit

###
### Node
###
# yum -y install npm
# npm install -g express-generator
# cd /opt
# express --css stylus api
# cd api
# npm install
# npm install socket.io
# npm install mysql

# vi /etc/firewalld/services/node.xml
# cat /etc/firewalld/services/node.xml
<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>Node.js</short>
  <description>Service for SocketIO</description>
  <port protocol="tcp" port="3000"/>
</service>
#

# firewall-cmd --add-service=node --zone=public --permanent; \
firewall-cmd --reload; \
firewall-cmd --list-services --zone=public

# vi /etc/systemd/system/node.service
# cat /etc/systemd/system/node.service
[Unit]
Description=Node.js Server

[Service]
WorkingDirectory=/opt/api
Type=simple
ExecStart=/opt/api/bin/www
Restart=always
RestartSec=10
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=node-server
Environment=NODE_ENV=production PORT=3000
User=root
Group=root

[Install]
WantedBy=multi-user.target
#

# systemctl daemon-reload; \
systemctl enable node; \
systemctl start node; \
systemctl status node

###
### Check Express
###
# WEBブラウザで確認 http://192.168.56.130:3000

###
### vue CLI
###
# cd
# npm install -g @vue/cli

###
### Project Name: myapp
### My IP: 192.168.56.130
###
# firewall-cmd --zone=public --add-port=80/tcp --permanent; \
firewall-cmd --reload
# cd /opt
# vue create myapp
### ------------------------------------------------------
### 上下カーソルで"Manually select features"を選択しEnter。
### 上下カーソルで"router" をSapceキーで選択しEnter。
### 後はdefault。
### ------------------------------------------------------

###
### Check http://192.168.56.130
###
# cd /opt/myapp
# npm run serve -- --port 80
^C(Ctrl-C)で終了。

###
### myapp daemon
###
# vi /etc/systemd/system/myapp.service
# cat /etc/systemd/system/myapp.service
[Unit]
Description=MyWeb Application
After=network-online.target

[Service]
Restart=on-failure
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/npm run serve -- --port 80
CPUAccounting=true
CPUQuota=50%
MemoryAccounting=true
MemoryLimit=1024M

[Install]
WantedBy=multi-user.target
#

# systemctl daemon-reload; \
systemctl enable myapp

# systemctl start myapp
# systemctl status myapp

###########################################################################################
###
### ここからVueサンプルプログラム
###

###
### Test data
###
# mysql -u devusr -p devdb

MariaDB [devdb]> CREATE TABLE `album` (
    `id`     INT(11)      NOT NULL AUTO_INCREMENT,
    `artist` VARCHAR(100) NOT NULL,
    `title`  VARCHAR(100) NOT NULL,
    PRIMARY KEY (id)
);

MariaDB [devdb]> INSERT INTO `album` (`artist`, `title`) VALUES
('The Military Wives', 'In My Dreams'),
('Adele', '21'),
('Bruce Springsteen', 'Wrecking Ball (Deluxe)'),
('Lana Del Rey', 'Born To Die'),
('Gotye', 'Making Mirrors'),
("David Bowie", "The Next Day (Deluxe Version)"),
("Bastille", "Bad Blood"),
("Various Artists", "Call the Midwife (Music From the TV Series)");

MariaDB [devdb]> select * from album;
.....

MariaDB [devdb]> exit
#

###
### API
###
# cd /opt/api
# vi app.js
<<<
..........
var usersRouter = require('./routes/users');
var apiRouter   = require('./routes/api');    <-- 追加
..........
app.use('/users', usersRouter);
app.use('/api', apiRouter);                   <-- 追加
..........
>>>

# cd /opt/api/routes
# vi api.js
# cat api.js
var express = require('express');
var router = express.Router();

var mysql = require('mysql');

var db = mysql.createConnection({
  host: 'localhost',
  user: 'devusr',
  password: '...password...',
  database: 'devdb'
});

db.connect(function(err) {
  if (err) throw err;
});

var accessControlAllowOrigin = '*';

router.get('/', function(req, res, next) {
  var param = {"result": ""};
  res.header('Access-Control-Allow-Origin', accessControlAllowOrigin);
  res.send(param);
});

router.get('/list', function(req, res, next) {
  var sql = "SELECT `id`, `artist`, `title` FROM `album` ORDER BY `id` ASC"
  db.query(sql, function (err, result, fields) {
    if (err) throw err;
    var param = {"result": result};
    res.header('Access-Control-Allow-Origin', accessControlAllowOrigin);
    res.send(param);
  });
});

router.get('/get/:id', function(req, res, next) {
  var sql = "SELECT `id`, `artist`, `title` FROM `album` WHERE `id` = '" + req.params.id + "'"
  db.query(sql, function (err, result, fields) {
    if (err) throw err;
    var param = {"result": (result[0]) ? result[0] : []};
    res.header('Access-Control-Allow-Origin', accessControlAllowOrigin);
    res.send(param);
  });
});

module.exports = router;
#

# systemctl restart node

### check http://192.168.56.130:3000/api/list

###
### myapp
###
# cd /opt/myapp
# cd /opt/myapp/src
# vi main.js
# cat main.js
import Vue    from 'vue'
import App    from './App.vue'
import router from './router'
import axios  from 'axios'

Vue.config.productionTip = false
Vue.prototype.$axios     = axios

new Vue({
  router,
  render: h => h(App)
}).$mount('#app')
#

# cd /opt/myapp/src
# cp App.vue ~/
# vi App.vue
# diff ~/App.vue App.vue
5c5,6
<       <router-link to="/about">About</router-link>
---
>       <router-link to="/about">About</router-link> |
>       <router-link to="/list">List</router-link>
#

# cd /opt/myapp/src/components
# vi List.vue
<template>
  <div class="list">
    <div>
      <input @click="getList" type="button" value="リストを取得">
      <div v-if="result.length">
        <table class="vue_tbl" id="listTable">
          <thead>
            <tr>
              <th>ID</th>
              <th>Artist</th>
              <th>Title</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="(value, key) in result" :key="key">
              <td style="text-align: right;">{{ value.id }}</td>
              <td style="text-align: left;">{{ value.artist }}</td>
              <td style="text-align: left;">{{ value.title }}</td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'List',
  data: function() {
    return {
      result: [],
    }
  },
  methods: {
    getList() {
      this.$axios.get('http://192.168.56.130:3000/api/list/')
        .then((res) => {
          this.result = res.data.result;
        })
        .catch((e) => {
          alert(e);
        });
    }
  }
}
</script>

<style>
#listTable {
  margin-left: auto;
  margin-right: auto;
  border:1px solid #333;
}
#listTable th {
  border:1px solid #333;
}
</style>
#

# cd /opt/myapp/src/router
# cp index.js ~/
# vi index.js
# diff ~/index.js index.js
3a4
> import List from '../components/List.vue'
19a21,25
>   },
>   {
>     path: '/list',
>     name: 'List',
>     component: List
#

###
### エラー・チェック
###
# cd /opt/myapp
# npm run int

###
### 再起動
###
# systemctl restart myapp

###
### 動作確認 http://192.168.56.130/
###   1. Listアンカーをクリックし、listエレメントを表示。
###   2. [リストを取得]ボタンをクリックし、APIを呼び、その結果を表示する。
###

.end of line