はじめに
こちらは、エンジニアの新たな学びキャンペーンに向けた記事となります。
Node.js + Express で作る Webアプリケーション 実践講座を参考にしながら、
データベース(以下DB)内のデータを、Webブラウザに表示する方法を記事にしました。
なお、ここではNode.jsのテンプレートエンジンであるEJSと、RDB(リレーショナルデータベース)であるMariaDB(MySQL)を利用します。
(上記講座ではMongoDBが利用されていますが、本記事ではMySQLに置き換えました。)
実行環境
- Node.js v12.16.3
- Express 4.16.1
- 10.4.11-MariaDB
対象者
- JavaScriptの文法自体は学んだけど、Web技術はまだほとんど学べていない人
- かんたんなCRUD操作に関するSQLを理解している人
本記事でわかること
- サーバーサイド言語Node.js & フレームワークExpressを使い、Hello Worldする方法
- ExpressとMariaDB(MySQL)の連携方法
- ExpressとMariaDB(MySQL)を使い、DB内のデータをWebブラウザ上に出力する方法
対象のUdemy講座で学んだこと
対象の講座で学んだことのうち、特に本記事へ反映する内容は以下となります。
- パッケージマネージャであるnpmを使い、ミドルウェアやフレームワークを導入する方法
- EJSの構文の使い方
- Expressでのルーティング方法(特に関数の引数に関して)
EJSとは
EJSは、テンプレートエンジンと呼ばれるもののひとつで、
テンプレートエンジンはHTMLの中にプログラム言語を埋め込むことができます。
特にEJSにおいては、HTML文書の中に<% %>
, <%= %>
タグなどを埋め込み、この中にプログラムを記述します。
EJSの基本構文
EJSの基本的な書き方にきれいにまとまっていたので、
こちらを参照すると幸せになれます。
EJSの利点
EJSは、サーバーサイドで保持している変数の値を併用してHTMLを記述するとき、書きやすさ・読みやすさの点で非常に強力です。
例えばサーバーサイド言語のみでHTML文書を書く場合、次のようなソースコードになります。
const express = require("express");
const app = express();
app.get("/", (req, res) => {
const text = "Hello World";
let data = "<!DOCTYPE html>\r\n";
data += "<html>\r\n";
data += " <head>\r\n";
data += " <meta charset='UTF-8'>\r\n";
data += " <title>hoge</title>\r\n";
data += " </head>\r\n";
data += " <body>\r\n";
data += "<p>";
data += text
data += "</p>\r\n";
data += " </body>\r\n";
data += "</html>";
res.send(data);
});
app.listen(3000);
一方で、テンプレートエンジンを併用した場合は、次のようになります。
クォーテーションや改行を意味する\r\n
などが消え、読み書きしやすくなっているのが分かります。
const express = require("express");
const app = express();
app.set("view engine", "ejs");
app.get("/", (req, res) => {
const text = "Hello World";
res.render("index", {text});
});
app.listen(3000);
<!DOCTYPE html>
<html>
<head>
<meta charset='UTF-8'>
<title>hoge</title>
</head>
<body>
<p><%= text %></p>
</body>
</html>
実行の準備
さて、まずは環境の構築を行います。
Node.js, MariaDB(MySQL)はインストールされているものとします。
サーバーサイドの準備
以下のコマンドを順に実行して、フレームワークやミドルウェアを導入します。
$ npm init
-
$ npm install express --save
, $ npm install mysql
$ npm install ejs -- save
MariaDB(MySQL)の準備
以下のSQLを順に実行します。
この操作により、Webサイトの名前・URLに関するテーブルを作成し、データの追加も行います。
create database website
create table website(name varchar(255), url varchar(255));
insert into website(name, url) values ("google", "https://www.google.com/"), ("amazon", "https://www.amazon.co.jp/"), ("apple", "https://www.apple.com/"), ("facebook", "https://www.facebook.com/");
実装する
次のような順序で、簡単なことから実装していきます。
- EJSを使い、Webブラウザ上でHello Worldする
- DB接続を行いデータを取り出し、ターミナル上にデータを出力する
- DB接続を行い、EJSファイルを利用してWebブラウザ上にデータを出力する(ここでは一度失敗してみる)
- DB接続を行い、EJSファイルを利用してWebブラウザ上にデータを出力する(再チャレンジし、成功する)
1. EJSでHello Worldしてみよう
まずはDBのことは一旦 忘れて、EJSを使ってHello Worldをしてみます。
下記ソースコードを保存後、ターミナル上で$ node app.js
と入力し、
Webブラウザでhttp://localhost:3000/
にアクセスします。
次の画像のように表示されたら成功です。
ちなみに、
app.js
のソースコード内のapp.get()
の第一引数はリクエストURL、
第二引数はリクエストが送られたときに実行されるコールバック関数を指します。
この処理を口語的に説明するなら、
http://localhost:3000/
が呼ばれたら次のコールバック関数を実行してね!
そしてそのコールバック関数には、index.ejsを表示して!っていう命令も含まれてるよ!
といったところでしょうか。
実行するソースコード
const express = require("express");
const app = express();
app.set("view engine", "ejs");
app.get("/", (req, res)=>{
res.render("index.ejs"); // デフォルトでは /viewsからの相対パスで表すので注意
})
app.listen(3000);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>
2. DBに接続してみよう
次に、DB内のデータをターミナル上で表示する実装を行います。
app.js
を次のように書き換えます。
なお、mysql.createConnection()
の各種ユーザ情報は、必要に応じて書きかえてください。
実行するソースコード
const express = require("express");
const app = express();
const mysql = require("mysql");
const connection = mysql.createConnection({
host: "localhost",
user: "root",
password: "1234",
database: "website"
});
app.set("view engine", "ejs");
app.get("/", (req, res)=>{
const sql = "select * from website";
connection.query(sql, (err, result, fields)=>{
if(err)throw err;
console.log(result);
})
res.render("index.ejs"); // デフォルトでは "/views"ディレクトリからの相対パスで表すので注意
})
app.listen(3000);
ターミナル上で$ node app.js
と入力し、Webブラウザでhttp://localhost:3000/
にアクセスします。
前回と同様にHello WorldがWebブラウザに表示されており、
更にターミナル上に、次のような表示があれば成功です。
ここではconsole.log(result)
の実行による、ターミナルのデータ出力結果から、
変数result
にはDBから取り出したデータが入っていることが確認できます。
$ node app.js
[
RowDataPacket { name: 'google', url: 'https://www.google.com/' },
RowDataPacket { name: 'amazon', url: 'https://www.amazon.co.jp/' },
RowDataPacket { name: 'apple', url: 'https://www.apple.com/' },
RowDataPacket { name: 'facebook', url: 'https://www.facebook.com/' }
]
3. DB内のデータをWebブラウザに表示してみる
『1.EJSでHello Worldしてみよう』, 『2.DBに接続してみよう』では、
res.render("index.ejs")
とレンダリング先を表記し、ルーティングを設定していました。
今回はレンダリング先にデータを渡すために、
app.get()
内にレンダリング先だけではなく、DBから取得したデータも記述する必要があります。
そこでres.render()
の第二引数に、レンダリング先に送るデータを記述します。
より具体的にはいえば、
『2. DBに接続してみよう』で、変数result
にDBのデータが格納されることが確認できていました。
このresultをres.render()
の第二引数に指定します。
従って、ここではres.render("index", { web: result})
と記述します。
ところで{ web: result}
という記述に、ややこしさを感じるかもしれません。
これはresultからwebへ名前を置換してから、データを送るという処理を含んでいます。
EJSに対して、resultという変数名をそのままに渡してしまうと、
「result?結果?いや何の結果を表す変数なのか、なんのこっちゃわからん」と、
フロントエンドエンジニアが困惑することになってしまいます。
(webという変数名ならば適切なのかという問題はさておき。)
実行するソースコード
DBに保存しているWebサイト名やURLをWebブラウザ上に出力するため、
app.js
とindex.ejs
を、それぞれ次のように書き換えます。
const express = require("express");
const app = express();
const mysql = require("mysql");
const connection = mysql.createConnection({
host: "localhost",
user: "root",
password: "1234",
database: "website"
});
app.set("view engine", "ejs");
app.get("/", (req, res)=>{
const sql = "select * from website";
connection.query(sql, (err, result, fields)=>{
if(err)throw err;
console.log(result);
res.render("index", { web: result});
})
})
app.listen(3000);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<h1>Hello World</h1>
<%= web %>
</body>
</html>
ターミナルにnode app.js
を入力し、Webブラウザでhttp://localhost:3000/
にアクセスします。
次の画像のような、Hello WorldとObjectという文字の羅列が確認できるでしょうか?
半分だけ成功です!
本来であればGoogle
やApple
といったWebサイト名や、
https://www.google.com/
のようなURLがほしかったところですが、
DBから何らかのデータを取り出すことには、ひとまず成功したのではないでしょうか。
[]
で囲まれたよくわからないものは4つで、DBに登録したレコードもちょうど4つでしたしね。
次の項で、この問題を解決します。
4. DB内のデータをWebブラウザに表示してみる(再挑戦)
前項ではDBから、どうやら何らかのデータを取り出すことには成功しましたが、
Webサイトの名前やURLを取得することはできませんでした。
この原因について考えます。
http://localhost:3000/
にアクセスしたとき、
console.log(result)
の実行によって、ターミナルに何か表示されたことは覚えているでしょうか?
それは、次のような内容でした。
$ node app.js
[
RowDataPacket { name: 'google', url: 'https://www.google.com/' },
RowDataPacket { name: 'amazon', url: 'https://www.amazon.co.jp/' },
RowDataPacket { name: 'apple', url: 'https://www.apple.com/' },
RowDataPacket { name: 'facebook', url: 'https://www.facebook.com/' }
]
一見するとオブジェクトですが、
出力されたデータは[]
で囲まれているため、これはオブジェクトたちを格納している『配列』です。
従って、例えばgoogle
を取得する場合はweb[0]["name"]
と記述します。
実行するソースコード
例として、google
とhttps://www.google.com/
をWebブラウザ上に表示してみます。
次のようにindex.ejs
を書き換え、再度 $ node app.js
で実行します。
下記画像のように、Webサイト名とURLが表示されたら、成功です。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<h1>Hello World</h1>
<%= web[0]["name"] %>
<br>
<%= web[0]["url"] %>
</body>
</html>
この他にも応用として、
for文を利用するなどして、一度に複数のデータを出力すること、
あるいはSQLを変更してデータの更新・追加・削除することも可能です。
おわりに
プログラミングを本格的に始めて1年も満たない未熟者の言葉ではありますが、
プログラミング言語の文法を修めるだけでは、Webのシステム開発は正直 不可能です。
私はJavaScriptの文法を学習した後、サーバーサイド言語としてのJavaScript(Node.js)に入門したのですが、
すぐにHTTPリクエスト、ルーティングなどといったWeb特有の専門用語に悩まされました。
Webアプリケーションのサーバーサイドへ入門する前に、
『この一冊で全部わかるWeb技術の基本』, 『Webを支える技術』, 『Web技術速習テキスト』といったWeb周りの情報に触れておくことを、強くおすすめします。