九保すこひ@フリーランスエンジニア|累計300万PVのブログ運営中
さてさて、これまでこのブログではLaravel
やVue
の記事を多く公開してきましたが、この度「より高速に動くサイト」を開発する可能性が出てきたので、これまで虎視眈々と狙っていたNode.js
のフレームワーク「Express」も少しずつ記事として紹介していけたらな、と考えています。(といってもメインは大好きなLaravel
で不動ですが😊)
そこで!
今回は、まずはExpress
をインストールする方法と、さらに、Express
を使う基本的な内容をまとめてみることにしました。
ぜひ皆さんのお役に立てると嬉しいです。
開発環境: Node.js 8.10、Ubuntu 18.04、nginx 1.14
目次
フォルダを用意する
まずExpress
をインストールするフォルダをつくります。
※ フォルダ名はお好みで変更してください。
Expressをインストールする
ターミナルで先ほど作成したフォルダに(cd
コマンドで)移動し、以下のコマンドを実行してnpm
を初期化します。
npm init
※ 色々と質問されますが、めんどうな場合はEnter
キー連打で終了させるか-y
をつけて質問をスキップしてください。
次にExpress
の本体をインストールします。
npm install express --save
インストールが完了するとフォルダ内は、次のようになります。
ウェブサーバー用のコードをつくる
続いて、ブラウザからExpress
にアクセスできるようにウェブサーバーが起動できるようにしましょう。
まずは、「package.json」を開いて「scripts > start」の部分を以下のように書き換えてください。
{ "name": "express41", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "start": "nodejs app.js" }, "author": "", "license": "ISC", "dependencies": { "express": "^4.17.1" } }
※ 注意:Ubuntu
の場合Node.js
のコマンドはnode
ではなくnodejs
です。もしnode
で実行したい場合は、以下のコマンドでシンボリックリンクを作っておくといいでしょう。
sudo ln -s "$(which nodejs)" /usr/bin/node
続いて、同じフォルダ内に「app.js」を作成し中身を以下のようにします。
const express = require('express'); const app = express(); app.get('/', (req, res) => { res.send('うまく動いてます!'); }); // 5000番ポートで待機 const PORT = process.env.PORT || 5000; app.listen(PORT, () => { console.log(`${PORT}番のポートで待機中です...`); });
続いて、以下のコマンドを実行してnpm
を起動します。
npm start
すると、以下のような表示になります。
これで、ウェブサーバーの設定は完了です。
では、実際にブラウザから「http://localhost:5000」にアクセスしてみましょう。
独自ドメインをつかう
もちろんこのまま開発を進めてもいいでしょうが、「localhost:5000」では開発するサイトが増えてくると、どれがどのサイトかわからなくなってしまいます。
そこで、今回は「http://express41.test」にアクセスすると、今回作ったExpress
アプリが実行できるようにしてみましょう。
まず、「/etc/nginx/sites-available/default」を開いて以下のコードを追加して保存します。
server { listen 80; server_name express41.test; location / { proxy_pass http://localhost:5000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; proxy_set_header X-Forwarded-For $remote_addr; } }
【追記:2020.02.04】IPアドレスを取得するために最後の行を追加しました。これがないと全てローカルからの接続になるので「::ffff:127.0.0.1」になってしまいます。なおIPアドレスを取得するには以下のようにします。
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
保存したらnginx
を再起動してください。
sudo systemctl restart nginx
次に「express41.test」がローカルに向くようにします。
※ ここからは「windows 10編」と「Ubuntu 18.04編」に別れます。ご自身の環境に合わせて読み進めてください。(・・・といっても、ほとんどwin 10だと思いますが😅)
Windows 10編
まず、検索ボックスに「notepad」と入力してメモ帳を表示させます。
そのままクリックせず、右クリックをして「管理者として実行」をクリック。
確認のポップアップが表示されるので「はい」をクリック。
メモ帳が起動するので、「ファイル > 開く」をクリック。
「c:\Windows\System32\Drivers\etc」を選択 すると(おそらく)何も表示されないので、右下の表示ファイルタイプを「すべてのファイル」に変更し、「hosts」を開く。
最終行に「127.0.0.1 express41.test」を追加して保存する。
Ubuntu編
以下のコマンドを実行します。
sudo gedit /etc/hosts
テキストエディタが開くので、
127.0.1.1 express41.test
を追加して保存してください。
ブラウザで確かめる
では、ブラウザから「http://express41.test」にアクセスしてみましょう。
直接アクセスできる「public」フォルダをつくる
例えば、画像やHTML
、CSS
、(ブラウザ側の)JS
ファイルに直接アクセスできるようにしてみましょう。
今回は以下の画像を使います。(神戸ポートタワー近くに展示されているクリスタル・ピアノです😊)
では、まずは「/public/images」フォルダをつくって、そこに「crystal_piano.jpg」を設置します。
次に、「app.js」で「public」フォルダに直接アクセスできるよう以下のコードを追加します。
const express = require('express'); const app = express(); app.get('/', (req, res) => { res.send('うまく動いてます!'); }); // ここ↓↓↓ app.use(express.static('public')); // 5000番ポートで待機 const PORT = process.env.PORT || 5000; app.listen(PORT, () => { console.log(`${PORT}番のポートで待機中です...`); });
注意:ここで注意が必要なのが、「app.js」に変更を加えた場合は必ずnpm
を再起動しないといけいないということです。
つまり、「Ctrl+C」などでストップしてもう一度以下のコマンドを実行しないと変更箇所が反映されません。
npm start
これで、「http://express41.test/images/crystal_piano.jpg」にアクセスすると、「public/images/crystal_piano.jpg」の画像が表示されることになります。(URLにはpublic
は不要ですので注意してください)
データベースにアクセスする
今回はexpress41
という名前のデータベースをMySQL
で用意して、そこからデータを管理できるようにします。
まずは、以下のコマンドでmysql
のパッケージをインストールしましょう。
npm install mysql
インストールが完了したら、MySQL
にデータベースを作り、テストとしてusers
というテーブルをつくります。
※ なお、DBの文字コードはLaravel
と同じく utf8mb4_unicode_ci
を使っています。
また、テスト用に以下のようなユーザーデータも追加しておきます。
続いて、このデータベースにアクセスできるようルートフォルダに「db.js」というファイルを作成し、中身を以下のようにしてください。
const mysql = require('mysql'); const db = mysql.createConnection({ host : '127.0.0.1', user : 'root', // DB接続ユーザー password : '**********', // DB接続パスワード database : 'express41' }); db.connect(err => { if(err) { // DBの接続に失敗 throw err; }; }); module.exports = db;
では、「app.js」に戻ってusers
テーブルからデータを取得してみましょう。(太字が追加した部分です)
const express = require('express'); const app = express(); const db = require('./db'); app.get('/', (req, res) => { const sql = 'SELECT * FROM users'; db.query(sql, (err, rows) => { if(rows.length > 0) { // データが見つかった場合 res.send(rows); } else { res.send('データが見つかりません。'); } }); }); // 省略
この状態で「http://express41.test」にアクセスすると、以下のようにDBデータがJSON
形式で表示されることになります。
[{"id":1,"name":"太郎","email":"taro@example.com"},(省略)}]
テンプレート・エンジンをつかう
Express
は多数のテンプレート・エンジンをサポートしていますが、今回はLaravel
のBlade
に近いmustache.js
を使うことにします。
まずは、以下のコマンドでパッケージをインストールしてください。
npm install mustache-express --save
次に、「app.js」でテンプレート・エンジンの設定をします。
const express = require('express'); const app = express(); const db = require('./db'); // テンプレート const mustacheExpress = require('mustache-express'); app.engine('mst', mustacheExpress()); app.set('view engine', 'mst'); app.set('views', __dirname + '/views'); app.get('/', (req, res) => { res.render('index', { title: 'ページタイトル', message: 'テストメッセージ' }); }); // 省略
これで、views
フォルダの中にある.mst
という拡張子がついたファイルがテンプレートとして使えるようになりました。
「/views/index.mst」を作成して中身を次のようにしてください。
<!DOCTYPE HTML> <html> <head> <title>{{ title }}</title> </head> <body> <div> {{ message }} </div> </body> </html>
では、この状態でもう一度「npm start」を使って再起動してブラウザから見てみましょう。
配列をループする
mustache.js
で配列をループするには、まず配列をパラメータとしてセットします。
res.render('index', { numbers: [1, 2, 3, 4, 5] });
そして、テンプレート・ファイルの方で以下のようにするとループすることができます。
{{ #numbers }} <ul> <li>{{ . }}</li> </ul> {{ /numbers }}
コレクションをループする
mustache.js
でオブジェクトが配列としてまとまった、いわゆる「コレクション」をループするには次のようにします。
まずは、パラメータとしてセットします。
res.render('index', { users: [ {name: '名前1', email: 'test1@example.com'}, {name: '名前2', email: 'test2@example.com'}, {name: '名前3', email: 'test2@example.com'}, ] });
テンプレートの中でのループはこのようになります。
{{ #users }} <ul> <li>{{ name }}: {{ email }}</li> </ul> {{ /users }}
実行結果です。
ルートを分割する
ここまででは、「app.js」内にルートを作って実行してきましたが、開発を進めていく上で、さすがに全てのルートを同じファイル内に書いてしまうと、どこに何があるかが分かりにくくなってしまうので、ルートを分割する方法をご紹介します。
まず、「routes」というフォルダをつくり、その中に「users.js」というファイルを作成します。
そして、中身は以下のようにしてください。
const express = require('express'); const router = express.Router(); router.get('/', (req, res) => { res.send('「users」の一覧ページ'); }); router.get('/:id', (req, res) => { res.send('「users」の個別ページ'); }); module.exports = router;
続いて、「app.js」で以下のように設定します。
// ルート app.use('/users', require('./routes/users'));
では、npm
を再起動してブラウザで確認してみましょう。
この方法を応用すればミドルウェアを使って、/users
階層は要ログインにすることもできます。
ちなみに:id
の値を取得したい場合は以下のようにすればOKです。
router.use(express.json()); router.use(express.urlencoded({ extended: true })); router.get('/:id', (req, res) => { const userId = req.params.id; });
おわりに
ということで、今回は新たな試みとしてNode.js
のフレームワークExpress
を使って基本的な内容をまとめてみました。
ちなみに、初めて本格的にExpress
を使ってみた雑感ですが、やはり「いかにLaravel
が便利機能をたくさん持っているか」を実感しました。
というのも、Laravel
だとDBテーブルを管理するマイグレーションが標準搭載していますし、ログイン機能も(最近パッケージとして分離されましたが)最初から存在しています。また、DBモデル(Eloquent
)のようなものがExpress
にはないので、これも自前で実装するかパッケージを使う、もしくはSQL文を直に書く必要があります。
となると、やはり保守管理や開発スピードを考えるとLaravel
の方が優位かなと感じています。(Express
初心者なので重要な部分が抜けている可能性は高いですが・・・)
また、Node.js
の一番の欠点は「エラーが発生すると、サーバーが落ちる」。これにつきます😫(ただし、この点に関しては解決する方法もあるそうなので、今後掘り下げて調査していこうかと考えています)
ただ、やっぱり実行スピードの高速化というのはとても大きな魅力なので、もう少し使ってみようなかなという感じです。
皆さんもぜひExpress
にチェレンジしてみてくださいね。
ではでは〜!
「遅れましたが、新年あけましておめでとうございます。
本年も「Console dot Log」をよろしくお願いいたします。m_ _m✨」