Node.js+MySQL+ExpressでWebアプリをつくる その1【MySQLにデータベースを作成して、それを表示する】
前提
・Node.jsのインストール
package.jsonの生成
好きな場所に「pj」フォルダを作り、package.jsonを生成する
cd pj
npm init --yes
※package.jsonとは
インストールしたnpmパッケージの一覧を記述したjsonファイル
※npmとは
Node Package Managerの略。Nodeにおけるパッケージ(=拡張機能)を管理するためのツール
npmパッケージのインストール
今回は2つのパッケージをインストールする
ejs
Embedded JavaScriptの略
HTMLのコードの中にJavascriptを埋め込むことができるようになるnpmパッケージ
express
テンプレートエンジンと呼ばれるもの
Staticなテンプレートファイルを基に、そのファイル内の変数などを置き換えてHTMLファイルを作成してクライアント(ブラウザ)に返す機能をもっている
npm install ejs
npm install express
ファイルの新規作成
pjフォルダ直下にapp.jsを作成し、次のコードを記述する
// expressの読み込みと使用準備
const express = require('express');
const app = express();
// expressにおけるルーティング
app.get('/', (req, res) => {
res.render('index.ejs');
});
// サーバーをローカルホストのどこで立ち上げるか指定する
app.listen(3000);
pjフォルダ直下にviewsフォルダを作成し、その中にindex.ejsを新規作成してh1タグを記述する
<h1>Hello!</h1>
CSSの適用
CSSや画像ファイルはpublicディレクトリに置くこと
publicディレクトリを新規作成し、その中にcssディレクトリをつくり、その中にstyle.cssをつくる
このままではCSSが適用されないので、app.jsに
app.use( exress.static('public') );
と書き、publicディレクトリ内のファイルを読み込めるようにしておくこと
あとはindex.ejsにlinkタグを設置するだけ
<link rel='stylesheet' href='/css/style.css'> // publicフォルダを起点としたパス
画像を使う
画像もpublicディレクトリ内に置くこと
publicディレクトリ内にimageディレクトリをつくり、その中にtop.pngを置く
index.ejsには
<img src='/image/top.png'> // publicフォルダを起点としたパス
サーバーの起動
サーバーを起動して「localhost:3000」というURLにアクセスする
node app.js
Error Failed to lookup view “hello.ejs” in views directory
アプリケーションディレクトリーの直下にviewsディレクトリがないときに発生するエラー
viewsディレクトリを作成し、その中にindex.ejsを置くこと
nodemon のインストール
このままだとjsファイルを更新した際にはサーバーを再起動しないと反映されない
Ctrl+Cでサーバーを停止した後に、node app.jsでサーバーを再起動しないといけない
毎回サーバーを再起動するのがメンドウな場合は、
ファイル更新時に自動でサーバーを再起動させてくるnpmパッケージ「nodemon」をインストールする
npm install -g nodemon
nodemonでサーバーを起動する場合は
nodemon app.js
※これを実行して以下のエラーが発生した場合は(https://rainbow-engine.com/ps-script-execution-disabled/)を参照してください。
ーーーーー
nodemon : このシステムではスクリプトの実行が無効になっているため、ファイル C:\Users\xxxxx\AppData\Roaming\npm\nodemon.ps1 を読み込むことができません。
ーーーーー
MySQLのインストール
まず、MySQLがすでにインストールされていないか確認する
mysql --version
インストールされていない場合は(https://dev.mysql.com/downloads/mysql/)からダウンロードすること
※Progateではversion5.7をインスコしているけれど、2023年10月にサポート終了するので最新バージョンをインストールした
手順は(https://prog-8.com/docs/mysql-env-win)を参照
MySQLを起動してログインする
MySQLは起動しないとログインできないので注意
net start mysql57 // progateではバージョン5.7だが、最新版LTSは8.4なので注意
mysql --user=root --password
※これで接続できない場合は、MySQL Command Line Client から接続したほうがいい
データベースの作成
データベースを作成したらSHOWでデータベースの一覧を確認すること
※クエリの最後にセミコロン(;)を忘れずに
CREATE DATEBASE db1;
SHOW databases;
テーブルの作成
usersという名前のテーブルを作成する
USE db1;
SHOW tables; // 作ったばかりのデータベースなのでテーブルが存在しないことを示すEmpty setが表示される
CREATE TABLE users (id INT AUTO_INCREMENT, name TEXT, PRIMARY KEY(id)) DEFAULT CHARSET=utf8;
SHOW tables; // テーブルが作成されているか確認する
DESCRIBE users; // テーブル構造を確認する
※プライマリーキーとはレコードを識別するための制約で、設定したカラムには重複する値を挿入できなくなる
テーブルにデータを挿入する
SELECT * FROM users; // usersテーブルが空であることを確認
INSERT INTO users(name) VALUES ('山田太郎');
SELECT * FROM users;
※テーブルやデータベースの削除
// テーブルの削除
SHOW tables;
DROP TABLE users;
// データベースの削除
SHOW databases;
DROP DATABSE db2;
mysqlパッケージのインストール
アプリケーションフォルダの直下で下記コマンドを実行
npm install mysql
MySQLへの接続情報を記述する
app.jsに接続情報を記述する
// 最初にexpressのインスタンスを生成しておく
const express = require('express');
const app = express();
// インスタンスを生成
const mysql = require('mysql');
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '', // 初期値は空
database: '' // データベース名(この記事ではdb1という名前でデータベースを作成した)
});
MySQLへ接続する
app.jsに下記コードを記述し、接続成功した場合にはconsole.logで出力する
app.get('/index', (req,res) => {
connection.connect( (err) => {
// 接続できない時はエラーを表示
if(err) {
console.log('エラー発生:' + err.stack);
return;
}
// 接続成功した場合の処理を記述する
console.log('接続成功');
// クエリの実行&その後の処理
connection.query(
'SELECT * FROM users',
(error, results) => {
console.log(results);
// usersテーブルの中身を{プロパティ:値}の形でindex.ejsに渡す
res.render('index.ejs', {users: results});
}
);
});
});
index.ejsで値を表示する
app.jsで受け取ったプロパティusersを使って、idやnameを表示する
<ul>
<% users.forEach( (user) => { %>
<li>
<%= user.id %>
<%= user.name %>
</li>
<% }); %>
</ul>
一旦サーバーを立ち上げてみる
エラー1「code: ‘MODULE_NOT_FOUND’」
code:–の前にError:Cannot find module ‘mysqwl’ って書いてある
mysqlの綴りを間違えてた
エラー2「Error: ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server;」
和訳すると「クライアントはサーバーから要求された認証プロトコルをサポートしていません」
MySQL5.7までとMySQL8.0以降でパスワードの認証形式(authentication protocol)が違うから起きるエラー
下記コマンドで認証パスワードを見てみよう
mysql> SELECT user, host, plugin FROM mysql.user;
MySQL5.7まではmysql_native_passwordというプラグインを使ってパスワードを暗号化していたが、MySQL8.0以降はcaching_sha2_passwordというプラグインを使ってパスワードを暗号化している
なので、下記コマンドで認証プラグインを変更するか、
mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
もしくはmysql2というnpmパッケージを使うこと
(https://www.chuken-engineer.com/entry/2020/09/04/074216)
npm install mysql2
mysql2 ならcaching_sha2_passwordの状態でも無事に接続できる
ただし、当然、app.jsファイル内では
const mysql = require('mysql2');
としなければならない
エラー3「index.ejsにてCannot read properties of undefined (reading ‘forEach’)」
和訳すると「undefinedのforEachというプロパティは読み込めませんよ」という意味
例えば、 <% users.forEach( (user) => {}); としているならusersがundefinedなのでforEachもundefinedになってしまう
エラー4「Access denied for user ‘root’@’localhost’ (using password: NO)」
和訳すると、パスワードがねえから開かねえぞ という意味。
password: passwordとしてみたら接続できた
エラー5「TypeError: req.next is not a function」
res.render(‘index.ejs’)を2回書いてた
MySQLを切断
connection.end();