Progate Node.js

Node.js I

  • express: npm install express
  • Embedded JavaScript: npm install ejs
    • 以下の開始括弧から閉じ括弧までが複数行にまたがってもよい
    • <% jsの構文 %>
    • <%= 変数 %> で変数を埋め込む
// ./app.js
const express = require('express');
const app = express();

app.use(express.static('public')); // CSSや画像ファイルを置くフォルダ(./public)を指定

app.get('/top', (req, res) => {
  const items = [
    { name: "hoge", id: 3 },
    { name: "fuga", id: 5 }
  ]
  res.render('top.ejs', {items:items});
  //  /top を GET すると ./views/top.ejs を描画する
  // 第二引数は ejs に渡すオブジェクト
});

app.listen(3000); // サーバを立ち上げるポートを指定
<!-- ./views/top.ejs -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Hello World</title>
    <link rel="stylesheet" href="/css/style.css">
    <!-- css の href は ./public からのパスを指定 -->
    <script src="/send_url.js"></script>
  </head>
  <body>
    <h1>Hello World</h1>
    <a href="/">トップへ戻る</a> <!-- 内部遷移はパスのみでOK -->
    <img src="/image/top.png"> <!-- 画像のパスも ./public から -->
    <ul class="table-body">
    <!-- ejs はこんな感じの forEach などでループを組むとよい -->
        <% items.forEach((item)=>{ %>
            <li>
                <span class="id-column">
                    <%= item.id %>
                </span>
                <span class="name-column">
                    <%= item.name %>
                </span>
            </li>
        <% }) %>
    </ul>
  </body>
</html>
/* ./public/css/style.css */
html {
  font-size: 100%;
  font-family: 'Hiragino Sans', sans-serif;
  line-height: 1.7;
  letter-spacing: 1px;
}
  • あと, ./public/image/top.png が必要
  • node app.js として実行すれば http://localhost:3000 でアクセスできる。

Node.js II

  • npm install mysql
  • ブラウザのリロードは直前のリクエストをもう一回行う機能。直前にPOSTしているともう一回POSTされてしまう。
  • よって, POST の後の結果の取得はリダイレクトさせたほうが良い。
const express = require('express');
const mysql = require('mysql');

const app = express();
app.use(express.static('public'));
app.use(express.urlencoded({extended: false}));
// http://expressjs.com/en/4x/api.html#express.urlencoded

const connection = mysql.createConnection({ // 接続情報の定義
  host: 'localhost',
  user: 'root',
  password: 'password',
  database: 'list_app'
});
// connection.query('クエリ', クエリ実行後の処理) でクエリを DB に対して実行して結果を受け取る

app.get('/index', (req, res) => {
  connection.query("SELECT * FROM tableA", (error, results) => {
    // results は {"カラム名1":値, "カラム名2":値} をレコード情報とするリスト
    res.render('index.ejs', {items: results});
  })
});

app.post('/create', (req, res) => { // index.ejs で POST されることを想定
  // データベースに追加する処理を書いてください
  connection.query(
    "INSERT INTO items(name) VALUES (?)",
    // クエリに変数を与えたい場合は第一引数のクエリに ? を用いる
    // ? には第二引数の配列要素が入る
    [req.body.postInfo],
    // その場合, 第三引数がクエリ実行後の処理
    (error, results) => {
      res.redirect("/index"); // クライアントにリダイレクトせよという要求を行う
    }
  )
});
app.listen(3000);
<!-- POST するフォーム -->
<form action="/create" method="post">
    <input type="text" name="postInfo">
    <!-- /create に post された情報を express が受け取ってパースすると req.body.postInfo の値がフォームにテキスト入力した値になる -->
    <input type="submit" value="作成する">
</form>

Node.js III

DELETE 機能

app.post('/delete/:id', (req, res) => { // /delete/3 などを受け取ると
  // req.params.id に 3 が格納される
  connection.query(
    "DELETE FROM items WHERE id = ?",
    [req.params.id],
    (error, results) => {
      res.redirect('/index');
    }
  )
});
<!-- postでリクエストする時は入力する項目がなくてもフォームを使う -->
<form action="/delete/<%= item.id %>" method="post">
    <!-- /delete/3 などにPOST-->
    <input type="submit" value="削除">
</form>

PUT 機能

該当レコードの更新フォームを取得

<a href="/edit/<%= item.id %>">更新</a> <!-- /edit/53 など-->
  • 上により, req.params.id に 53 が入る
app.get("/edit/:id", (req, res) => {
  connection.query(
    "SELECT * FROM items WHERE id = ?",
    [req.params.id],
    (error, results) => {
      res.render('edit.ejs', {item: results[0]});
      // id に対応するレコードを渡す
    }
  )
})

更新情報をPOSTして一覧を取得

  • edit.ejs は更新フォーム
<form action="/update/<%= item.id %>" method="post">
<!-- フォームの送信先は /update/53 -->
    <input type="text" name="itemName" value="<%= item.name %>">
    <!-- value属性: フォームに入力済みでレンダリングされる -->
    <!-- name属性: POST 時点で送信される値の key -->
    <input type="submit" value="更新する">
</form>
  • POST 情報のうち, id と itemName の値により DB を更新してリダイレクト
app.post('/update/:id', (req, res) => {
  connection.query(
    "UPDATE items SET name = ? WHERE id = ?",
    // ? を複数用いた場合はその順番に配列が反映される
    [req.body.itemName, req.params.id],
    (error, results) => {
      res.redirect('/index');
    }
  )
});

Node.jsの開発環境を用意しよう!

windowsOS

  • Node.js (LTS) のインストール
  • 設定は全てデフォルト
    • ただし, Tools for Native Modules (C/C++コンパイラが必要なnpmモジュールが...) のみチェックを入れるとよい。
    • インストールの後に Chocolatey とかのインストールが自動で開始する。

      macOS

  • Node.js (LTS) のインストール
  • 設定は全てデフォルト

Node.jsの新規アプリケーションを作ろう!

cd <ディレクトリ>
npm init --yes
npm install express ejs
vi ./app.js
mkdir views
vi ./views/hello.ejs
node app.js
npm install nodemon # ファイルが変更されると自動でサーバーを再起動してくれる
./node_modules/.bin/nodemon app.js # nodemon でサーバを起動するとき (npm start できるようにしておくと楽)
// ./app.js
const express = require('express');
const app = express();
app.get('/', (req, res) => {
  res.render('hello.ejs');
});
app.listen(3000);
<!-- ./views/hello.ejs -->
<h1>Hello World</h1>

Node.jsアプリケーションとMySQLを接続しよう!

# データベース名: list_app
# テーブル名: users
# は作成済みとする。
# 以下ではそのDBに接続する。
npm install mysql
vi ./app.js
// ./app.js
const express = require('express');
const mysql = require('mysql');
const app = express();

const connection = mysql.createConnection({ // 接続設定
  host: 'localhost',
  user: 'root',
  password: '[設定したパスワード]',
  database: 'list_app'
});

connection.connect((err) => { // 接続できないときエラーを出力ようにする
  if (err) {
    console.log('error connecting: ' + err.stack);
    return;
  }
  console.log('success');
});

app.get('/', (req, res) => { // / を GET したとき
  connection.query(
    'SELECT * FROM items',
    (error, results) => {
      console.log(results); // DB の中身を標準出力するようにする
      res.render('hello.ejs');
    }
  );
});

app.listen(3000);