Tips

初心者向け入門!Node.jsの使い方を解説します【express, nodemon, ejs, nodeMailer, module.exports, require】

  • このエントリーをはてなブックマークに追加

「JavaScriptはわかるけどNode.jsは触ったことがない」
「Node.jsが流行っているけど使用するメリットやタイミングがよくわからない」
「JavaScriptでメール送信のようなバックエンドの処理ができることを知らない」

本日はそんな方に向けて、Node.jsに焦点を当ててその基本を詳しく解説していきます。

Node.jsはJavaScriptをサーバーサイドで実行できる素晴らしいプラットフォームであり、その柔軟性とパワーは多くの開発者に愛されています。

本記事では、Node.jsの基礎を固めるために必要な概念とツールに焦点を当てます。

Expressを使ったルーティングやNodemonによる自動リロード、EJSを使ったテンプレートエンジン、そしてNodeMailerを使ったメールの送信といった実用的な要素も触れていきます。

依存パッケージのインストールとインポート

まずはNodeをインストールしておく必要があります。

ReactやVueなどを触ったことのある人なら既に入っているはずですが、わからない人はどこでも良いのでターミナルを開いて以下のコマンドを実行して何が返ってくるか確認してみましょう。

node -v

上図のように数字が返ってくれば既にNodeがインストールされています。

一方で違った場合はインストールが必要ですので以下のサイトを参考にインストールしてみてください、WindowsとMacで方法が違うのを注意しましょう。

https://www.sejuku.net/blog/72545

続いてNodeがインストールされてから依存パッケージをコマンドによってインストールしていきます。

まずは以下を実行してpackage.jsonを入れます。

npm init -y

続いて以下のコマンドを実行します。

npm i express mongoose ejs

さらに以下のコマンドも実行します。

npm i --save-dev nodemon

ここまで来たら以下のようなディレクトリ構造になっているはずです。

- node_modules
- package.json
- package-lock.json

それではpackage.jsonを開いて以下の場所でコードを追加します。

{
  "name": "demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",

  // ここを追加する
    "start": "nodemon server.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "ejs": "^3.1.9",
    "express": "^4.18.2",
    "mongoose": "^8.0.3"
  },
  "devDependencies": {
    "nodemon": "^3.0.2"
  }
}

これによってnpm run startというコマンドで実行ができるようになります。

それではserver.jsというファイルを作っておきましょう。

- node_modules
- package.json
- package-lock.json
- server.js
console.log("テスト");

上記のようにコンソールログだけ書いてからnpm run startとコマンドで実行しましょう。

npm run start

上図のようにターミナル上にコンソールログのテキストが表示されていればOKです。

赤いログが表示されている場合はエラーですのでここまでの作業で飛ばしたものがあるか、そもそもNodeが入っていない可能性があります。

問題なければ冒頭のコマンドで色々と実行していた依存パッケージをコードで使用できるようにインポートしましょう。

// コンソールログを消して以下を追加
const express = require('express');
const mongoose = require('mongoose');
const nodemon = require('nodemon');

続いてexpressをインスタンス化することでいろんなメソッドを使うことができます。

ここから「JavaScriptでこんなメソッド見たことないな」というものが多く登場しますが、それらはexpressをインスタンス化することで使用できる特別なメソッドだと思ってください。

const express = require('express');
const mongoose = require('mongoose');
const nodemon = require('nodemon');
// ここを追加
const app = express();

先ほどはターミナルでコンソールログを実行しましたがブラウザの画面に表示させてみましょう。

const express = require('express');
const mongoose = require('mongoose');
const nodemon = require('nodemon');

const app = express();
// ここを追加
app.get('/', (req, res) => {
  res.render('index');
});
app.listen('5000');

コードを追加したらviewsというフォルダを手動で新規作成して中にファイルでindex.ejsを作成します。

- node_modules
- package.json
- package-lock.json
- server.js
- views
   - index.ejs
<!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>test</h1>
</body>
</html>

ターミナルでnpm run startと実行していれば次回からは同じコマンドは実行しなくても大丈夫です。

以下のようになってしまっている方は消している可能性が高いので再度「npm run start」と実行しておいてください。

それではブラウザでhttp://localhost:5000というURLを打って画面を表示させてみましょう。

上図のように表示できていれば問題ありません、テキストが画面に出ているのがわかります。

index.ejsというのはHTMLのように画面に表示するものを作れるファイルです。

HTMLとJavaScriptがわかっていれば扱えるものですので初めての人も大丈夫です。

続いて変数に入れたものを画面に表示させてみます。

const express = require('express');
const mongoose = require('mongoose');
const nodemon = require('nodemon');

const app = express();

app.get('/', (req, res) => {
 // ここを変更
  res.render('index', { text: "テスト" });
});
app.listen('5000');

変数名は自由に決めることができて今回はtextという名前の変数に文字列でテストを格納しました。

変数の中身を画面に表示する際にはindex.ejsにて<%=%>という特別なタグの中で変数を書くことになります。

<!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>test</h1>
 // ここを追加
  <h1><%= text %></h1>
</body>
</html>

画面をリロードすると先ほどのテキストに加えて変数に入れていた文字も表示されました。

通常のJavaScriptと違ってバックエンドで作成しているので画面に表示する際には特殊なタグを使用します。

これらをテンプレートタグなどと言ってRubyやPHPでも<?php ?>のような特殊なタグが用意されています。

続いては配列、オブジェクトのような複数のデータを繰り返し処理で取り出して表示してみます。

データについては通常DBやAPIから取ってくるのですが、今回は簡易的にserver.jsに手書きで作って使用します。

// モジュールのエクスポート、インポート
const express = require('express');
const mongoose = require('mongoose');
const nodemon = require('nodemon');

const app = express();

app.set('view engine', 'ejs');

app.get('/', (req, res) => {
 // ここを追加
  const data = [
    {
      title: 'タイトル',
      desc: '初投稿です。',
    },
    {
      title: '2回目',
      desc: '2回目の投稿です。',
    },
    {
      title: '3回目',
      desc: '3回目の投稿です。',
    },
  ];
 // ここを変更
  res.render('index', { text: data });
});


app.listen('5000');

配列dataにはオブジェクトが3つ格納されており、1個のオブジェクトはブログ記事だと思ってください。

まず配列dataをres.renderの変数textに代入しておきます。

続いてindex.ejsの中でforEachを使います。

<!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>test</h1>
  // ここを変更
  <% text.forEach((article) => { %>
    <div>
      <%= article.title %>
    </div>
    <div>
      <%= article.description %>
    </div>
  <% }) %>
</body>
</html>

forEachのような処理を書くときはテンプレートタグで<%=%>ではなく<%%>として書くことになっています。

さらに関数のように複数行にまたがるときは1行ごとにテンプレートタグを閉じるルールになっていますので上記のような書き方をしています。

画面をリロードするとテキストが複数になっていて、こちらはserver.jsで作っていた配列dataの中身であることがわかります。

なんとなくバックエンドで作ったものを画面に表示することが理解してもらえればと思います。

Node.jsにおけるモジュール、エクスポート、インポートの基本操作

簡単なWebサイトを例にお話しましたが何回かインポートという言葉が登場しました。

JavaScriptでは外部ファイル、ライブラリからコードを拝借することをモジュールと言い、モジュールを使用するにはエクスポートとインポートという作業が必要になります。

Node.jsに限らずReactなどのモダンJSでも必要になる考え方なので基本操作を紹介します。

例えば以下のファイルがあったとします。

const studentsData = [
  {
    id: '0001',
    name: 'tanaka',
    age: 20,
  },
  {
    id: '0002',
    name: 'yamada',
    age: 21,
  },
  {
    id: '0003',
    name: 'nakamura',
    age: 20
  },
];

const arr = [1, 2, 3, 4, 5];

配列がデータとして用意されていて、こちらの配列を別のJSファイルで使用したい場合にはまずエクスポートという文法が必要です。

例えば定数studentsDataであれば以下のように書きます。

const studentsData = [
  {
    id: '0001',
    name: 'tanaka',
    age: 20,
  },
  {
    id: '0002',
    name: 'yamada',
    age: 21,
  },
  {
    id: '0003',
    name: 'nakamura',
    age: 20
  },
];

const arr = [1, 2, 3, 4, 5];
// ここを追加
module.exports = studentsData;

module.exportsと書いて=で挟んだデータは他のJSファイルに取り込むことが可能になります。

取り込む側のファイルを用意して、以下のようにインポート文を書いて取り込みます。

const students = require('./modules_students');

console.log(students);
// 以下が表示される
// [{id: '0001',name: 'tanaka',age: 20,},{id: '0002',name: 'yamada',age: 21,},{id: '0003',name: 'nakamura',age: 20},]

requireというメソッドはmodule.exportsされているデータをファイルパスを指定することで取得できます。

インポートしたデータを定数studentsに代入すれば、そのままデータを自由に使用できます。

またインポートしたデータを書き換えても元のデータは書きかわりませんの安心してください。

しかし注意点としてはエクスポートしたファイル側で以下のように何かの関数やメソッドが実行された場合にはインポートした時点のその関数やメソッドが発動します。

const studentsData = [
  {
    id: '0001',
    name: 'tanaka',
    age: 20,
  },
  {
    id: '0002',
    name: 'yamada',
    age: 21,
  },
  {
    id: '0003',
    name: 'nakamura',
    age: 20
  },
];

const arr = [1, 2, 3, 4, 5];
// ここを追加
console.log("test")

module.exports = studentsData;
const students = require('./modules_students');

console.log(students);
// 以下が表示される
// test
// [{id: '0001',name: 'tanaka',age: 20,},{id: '0002',name: 'yamada',age: 21,},{id: '0003',name: 'nakamura',age: 20},]

エクスポートしたファイルとインポートしたファイルそれぞれにconsole.log()がありますので2つのログが出力されるわけです。

一般的にはエクスポートする側では関数やメソッドは定数に格納しておくだけで、実行まではしないようにしておくことが多いです。

ちなみに2つのデータをエクスポートするときにはオブジェクト形式にします。

const studentsData = [
  {
    id: '0001',
    name: 'tanaka',
    age: 20,
  },
  {
    id: '0002',
    name: 'yamada',
    age: 21,
  },
  {
    id: '0003',
    name: 'nakamura',
    age: 20
  },
];

const arr = [1, 2, 3, 4, 5];

// ここを変更
module.exports = {
  studentsData: studentsData,
  arr: arr,
};

通常のオブジェクト形式と全く同じでキーと値を指定します。

キーは自由に決めることができますが、今回は値の名前と同じにしました。

2つのデータをインポートしてみましょう。

// ここを変更
const data = require('./modules_students');

// ここを変更
console.log(data.students);
console.log(data.arr);
// 以下が表示される
// [{id: '0001',name: 'tanaka',age: 20,},{id: '0002',name: 'yamada',age: 21,},{id: '0003',name: 'nakamura',age: 20},]
// [1,2,3,4,5]

インポートした側もオブジェクトで受け取るのでキー名を指定すれば各自のデータが参照できます。

ちなみに分割代入で書いておくと少し短くことができます。

// ここを変更
const { studentsData, arr } = require('./modules_students');

// ここを変更
console.log(students);
console.log(arr);
// 以下が表示される
// [{id: '0001',name: 'tanaka',age: 20,},{id: '0002',name: 'yamada',age: 21,},{id: '0003',name: 'nakamura',age: 20},]
// [1,2,3,4,5]

データ名.キー名と「.」で繋げた書き方より分割代入でキー名のみを指定する方が簡単ですよね。

またエクスポートする側もキーと値が同じ名前なら値を省略して以下のように書くことが可能です。

const studentsData = [
  {
    id: '0001',
    name: 'tanaka',
    age: 20,
  },
  {
    id: '0002',
    name: 'yamada',
    age: 21,
  },
  {
    id: '0003',
    name: 'nakamura',
    age: 20
  },
];

const arr = [1, 2, 3, 4, 5];

// ここを変更
module.exports = {studentsData, arr};

ここまで2つのJSファイルを用意してモジュールを体験していましたが、ライブラリについてはエクスポートはすでにされているので必要なタイミングでインポートだけすれば使用できるようにできています。

例えばOSというライブラリがあるのですが以下のように、いきなりインポートして使用できます。

const { studentsData, arr } = require('./modules_students');

// ここを追加
const pc = require('os');

// ここを変更
console.log(pc.platform()); // Windowsならwin,Macならdarwinと表示される
console.log(pc.homedir()); // ホームディレクトリが表示される

試してもらえれば何か出力されたはずです。

module.exportsと書かないといけないのは自分で作ったデータやJSファイルのみで、すでにあるライブラリでは必要ありません。

nodeMailerを使ってメール送信をやってみる

続いてバックエンドならではの処理としてメールの送信をやってみたいと思います。

メール送信というとPHPのイメージが強いかもしれませんがJavaScriptでもNode.jsを使えばメールを送信することができます。

今回は初心者が簡単にメール送信を実装できるnodeMailerというライブラリを使います。

まずはターミナルで以下のコマンドを実行してnodeMailerをインストールしておきます。

npm i nodemailer

nodeMailerでテキストのメールを送る

ファイルについては前章までのとは変えたいので新しく作りましょう。

本記事ではapp.jsという名前にしてnodeMailerをインポートしておきます。

const nodeMailer = require('nodemailer');

続いてメール本文を定数htmlとして作成しておきます。

const nodeMailer = require('nodemailer');
// ここを追加
const html = `
  <h1>こんにちは</h1>
  <p>こちらはテストメールです。</p>
  <img src="cid:unique@gmail.com" width="400">
`;

続いて送信元の設定をしていきます、今回はGmailを使っているものとします。

const nodeMailer = require('nodemailer');

const html = `
  <h1>こんにちは</h1>
  <p>こちらはテストメールです。</p>
  <img src="cid:unique@gmail.com" width="400">
`;

// ここを追加
async function mailFn() {
  const transport = nodeMailer.createTransport({
    host: 'smtp.gmail.com',
    port: 465,
    secure: true,
    auth: {
      user: '自分のGmailアドレス',
      pass: 'SMTPアプリパスワード',
    },
  });
}
mailFn().catch((error) => console.log(error));

定数transportにはnodeMailerのcreateTransportという特別なメソッドで送信元の設定をします。

userプロパティには送信する人のGmailアドレスを文字列で書きます。

passプロパティについてはGoogleのアプリパスワードを文字列で書きます。

Googleの右上の自分のアイコンから「アカウント管理」をクリックします。

続いて左のサイドメニューからセキュリティをクリックします。

ヘッダーにある検索バーに「アプリパスワード」と検索して予測変換に表示されたものをクリックします。

そのまま画面が切り替わる場合もありますが、以下のように再度ログインを求められることもあります。

その場合はログインパスワードを入れると画面が切り替わります。

アプリパスワードでは今回のような外部のライブラリ、APIと連携させるための特別なパスワードを発行することができます。

ログインパスワードとは違うものになりますので注意しましょう。

まず名前を決めます、本記事では「nodemailer」としました。

名前を入力して作成ボタンをクリックするとパスワードが自動生成されてポップアップとして表示されます。

こちらは表示できるのは1回だけなのでメモにコピーしておいてください。

「完了」というボタンをクリックすると設定が終了します。

メモしたパスワードをコードのpassプロパティに貼り付けましょう。

const nodeMailer = require('nodemailer');

const html = `
  <h1>こんにちは</h1>
  <p>こちらはテストメールです。</p>
  <img src="cid:unique@gmail.com" width="400">
`;

async function mailFn() {
  const transport = nodeMailer.createTransport({
    host: 'smtp.gmail.com',
    port: 465,
    secure: true,
    auth: {
      user: 'lorem.co.ltd@gmail.com',
      pass: 'hmxzdcppnxragkpu',
    },
  });
}
mailFn().catch((error) => console.log(error));

あとは送信先の設定をします。

同じく関数mailFnの中で書いていきます。

// node -v
// npm init --y
// npm i nodemailer
// 設定→Googleの設定、Googleアカウントの管理→セキュリティ→2段階認証→アプリパスワード

const nodeMailer = require('nodemailer');

const html = `
  <h1>こんにちは</h1>
  <p>こちらはテストメールです。</p>
  <img src="cid:unique@gmail.com" width="400">
`;


async function mailFn() {
  const transport = nodeMailer.createTransport({
    host: 'smtp.gmail.com',
    port: 465,
    secure: true,
    auth: {
      user: '自分のGmailアドレス',
      pass: 'SMTPアプリパスワード',
    },
  });
 
  // ここを追加
  const info = await transport.sendMail({
    from: 'CodeTips<自分のGmailアドレス>',
    to: '送信先のアドレス',
    subject: 'テストです。',
    html: html,
  });
}
mailFn().catch((error) => console.log(error));

先ほどの定数transportにsendMailというメソッドでメールの送信内容を設定しています。

fromには自分のアドレス、toには送信先のアドレス、subjectには件名を入れました。

htmlプロパティは本文ですが先ほど定数htmlとして用意していましたのでhtmlを書きます。

送信先のアドレスは何でも大丈夫です、送信元と同じでも、アドレスを2個お持ちの方は使っていないアドレスを書いても良いです。

プログラムの実行をターミナルからやってみます。

node app.js

そうするとtoプロパティに書いたアドレスにメールが届いているはずです。

nodeMailerで画像を添付して送信する

続いてテキストだけでなく画像を添付してみましょう。

画像は何でも大丈夫なのでパソコンの中で用意しておきます。

- node_modules
- package.json
- package-lock.json
- app.js
- images
   - 画像ファイル

先ほどのコードに加筆する形で書いていきます。

sendMailの中のプロパティでattachmentsというものがあり画像などの添付ファイルを配列で指定できます。

// node -v
// npm init --y
// npm i nodemailer
// 設定→Googleの設定、Googleアカウントの管理→セキュリティ→2段階認証→アプリパスワード

const nodeMailer = require('nodemailer');

const html = `
  <h1>こんにちは</h1>
  <p>こちらはテストメールです。</p>
  <img src="cid:unique@gmail.com" width="400">
`;


async function mailFn() {
  const transport = nodeMailer.createTransport({
    host: 'smtp.gmail.com',
    port: 465,
    secure: true,
    auth: {
      user: '自分のGmailアドレス',
      pass: 'SMTPアプリパスワード',
    },
  });
 

  const info = await transport.sendMail({
    from: 'CodeTips<自分のGmailアドレス>',
    to: '送信先のアドレス',
    subject: 'テストです。',
    html: html,
   // ここを追加
  attachments: [
      {
        filename: 'csv',
        path: './images/file_icon_text_csv.png',
        cid: 'unique@gmail.com',
      },
      {
        filename: 'jpg',
        path: './images/file_icon_text_jpg.png',
        cid: 'unique@gmail.com',
      },
      {
        filename: 'txt',
        path: './images/file_icon_text_txt.png',
        cid: 'unique@gmail.com',
      },
    ],
  });
}
mailFn().catch((error) => console.log(error));

配列の中でファイル1個をオブジェクトにして格納するようにします。

filenameはファイル名でpathはファイルのパスを指定します、uidは識別番号ですが今回はunique@gmail.comとしておきましょう。

画像が複数あるときは上記コードのようにオブジェクトを増やしてくイメージです。

再度コマンドを叩いてメールを送信してみます。

node app.js

添付ファイル付きのメールアドレスが届いていますね。

今回は画像にしましたがpdfやcsvでも実行方法は同じ流れです。

nodeMailerで複数人にメールを送信する

最後に同じメールを複数人に送ってみましょう。

こちらはsendMail関数の引数の中でtoオブジェクトに修正を加えます。

事前にアドレスを配列として用意しておき、toプロパティに配列として指定します。

// node -v
// npm init --y
// npm i nodemailer
// 設定→Googleの設定、Googleアカウントの管理→セキュリティ→2段階認証→アプリパスワード

const nodeMailer = require('nodemailer');

const html = `
  <h1>こんにちは</h1>
  <p>こちらはテストメールです。</p>
  <img src="cid:unique@gmail.com" width="400">
`;



async function mailFn() {
  const transport = nodeMailer.createTransport({
    host: 'smtp.gmail.com',
    port: 465,
    secure: true,
    auth: {
      user: '自分のGmailアドレス',
      pass: 'SMTPアプリパスワード',
    },
  });
 
  // ここを追加
  const emails = ['送信先1', '送信先2'];

  const info = await transport.sendMail({
    from: 'CodeTips<自分のGmailアドレス>',

   // ここを修正
    to: mails,
    subject: 'テストです。',
    html: html,
  attachments: [
      {
        filename: 'csv',
        path: './images/file_icon_text_csv.png',
        cid: 'unique@gmail.com',
      },
      {
        filename: 'jpg',
        path: './images/file_icon_text_jpg.png',
        cid: 'unique@gmail.com',
      },
      {
        filename: 'txt',
        path: './images/file_icon_text_txt.png',
        cid: 'unique@gmail.com',
      },
    ],
  });
}
mailFn().catch((error) => console.log(error));

送信内容は先ほどと同じテキストと添付画像でやってみます。

複数人に送る時もコマンドは1回実行すればOKです。

node app.js

本記事ではGmailとYohooメールのアドレスを指定して、両方とも送信することができました。

画像もダウンロードしてパソコンの中で使用することができます。

普通のJavaScriptと書き方や途中過程が違うので最初は慣れないですが少しずつ覚えていきましょう。

Node.jsを使ってバックエンドを書くとフロントとバックエンドが1つの言語で統一することができます。

初学者のうちはいろんな言語が使えませんし、会社でも少人数でやっているチームは使用言語にバラツキがあるとプロジェクトが組めなかったりします。

そのためバックエンドにNode.jsを採用することが割とありますので興味がある方は勉強していきましょう。

今回参考にした本はこちらになります。

良ければこちらからどうぞ。

  • このエントリーをはてなブックマークに追加