メインコンテンツまでスキップ

モジュールとnpm

別のファイルに書かれたプログラム

Node.jsでは、あるファイルに書かれたプログラムは、別のプログラムからは読み込めません。よって、次のmain.mjsはエラーになります。

sub.mjs
function add(a, b) {
return a + b;
}
main.mjs
console.log(add(3, 4)); // Uncaught ReferenceError: add is not defined

別のファイルに書かれたプログラムを読み込むための手段として、Node.jsではモジュールという仕組みが用意されています。JavaScriptでは、すべてのファイルがモジュールとして扱われます。

Node.jsでは、ファイルの拡張子が.mjsの場合、export文やimport文を用いて他のモジュールとのやりとりを行います。

sub.mjs
export default function add(a, b) {
return a + b;
}
main.mjs
import add from "./sub.mjs";
console.log(add(3, 4));
名前付きエクスポート

上のようにデフォルトエクスポートを使うと各モジュールで複数の関数をエクスポートすることができません。その場合は、名前付きエクスポートを用いることができます。

sub.mjs
export function add(a, b) {
return a + b;
}

export function subtract(a, b) {
return a - b;
}
main.mjs
import { add, subtract } from "./sub.mjs";
console.log(add(3, 4));
console.log(subtract(4, 3));
CommonJSモジュール

さきほどのようにexport文とimport文を用いて他のモジュールとのやり取りを行うJavaScript標準のモジュールシステムを、ECMAScriptモジュールと呼ぶ場合があります。Node.jsでは、拡張子を.mjsにすることで、ECMAScriptモジュールを用いてプログラムを記述できます。

ECMAScriptモジュールの他にCommonJSモジュールと呼ばれるものもあります。CommonJSモジュールでは、exportsオブジェクトやrequire関数を用いて他のモジュールとのやり取りを行うことができます。Node.jsでは、拡張子を.jsにすることで、CommonJSモジュールを用いてプログラムを記述できます。

exportsオブジェクトは標準では空のオブジェクトですが、プログラム中から書き換えることができます。

require関数に別のファイルへの相対パスを指定すると、そのファイルを実行した後にできるexportsオブジェクトを取得できます。

sub.js
exports.add = (a, b) => {
return a + b;
};
main.js
const sub = require("./sub"); // sub = { add: (a, b) => { return a + b; } }
const add = sub.add;
console.log(add(3, 4));

標準モジュール

Node.jsのfsモジュールを用いると、Node.jsからファイルの読み書きを行うことができます。fsモジュールのreadFileSync関数は、ファイルの読み込みを行う関数で、第1引数にファイルへのパスを指定し、第2引数には文字コードを指定します。

main.mjs
import { readFileSync } from "node:fs";
console.log(readFileSync("./sample.txt", "utf-8"));
sample.txt
Hello World!
文字コード

文字コードとは、文字のコンピューターによる表現です。UTF-8Shift_JISなどさまざまな方式が定義されていますが、現在では通常UTF-8を選んでおけば問題ありません。間違った方式を選んでしまうと、意図と異なる文字として解釈されてしまう現象 (文字化け)が起こります。

演習

fsモジュールのwriteFileSync関数を用いて、ファイルに文字列を書き出してみましょう。

解答例

第1引数にファイルへのパス、第2引数に書き込む文字列を指定します。

main.mjs
import { writeFileSync } from "node:fs";
writeFileSync("./sample.txt", "Hello World!");

npm

Node.jsにおけるパッケージとは、主にJavaScriptファイルをまとめていろいろな場所で利用可能にしたものです。npm (Node Package Manager) は、Node.jsのパッケージマネージャーで、このソフトウェアを通してパッケージを管理できます。

また、npmから利用されるパッケージを集積したサービスnpmjs.comもまた、npmと呼ばれます。例として、日付や時刻の操作のために用いられるライブラリである、date-fnsパッケージを利用してみましょう。

npmを用いて開発を行うには、まずnpm initコマンドを実行します。いくつか質問をされるので、Enterキーを押し続けて質問をスキップしましょう。完了すると、フォルダの中にpackage.jsonという名前のファイルが作成されます。このファイルは、npmによって管理されるフォルダに必ず1つ必要になるものです。

続いて、npmのパッケージをインストールします。npm installに続けて、インストールしたいパッケージの名前を入力します。

npm install date-fns

これにより、フォルダの中にpackage-lock.jsonファイルと、node_modulesフォルダが作成され、内部にパッケージ本体がダウンロードされます。

JSON

npmによって作成されたpackage.jsonとは何者でしょうか。拡張子が.jsonのファイルには、JSONが記述されています。JSONは、JavaScript Object Notationの略で、複雑なデータ構造を単一の文字列として表現する際に、JavaScriptオブジェクトに似た記法を用いるための仕様です。JavaScriptとの相性が非常に良いだけでなく、文法が単純で明快であることから、JavaScriptを用いないプロジェクトでも頻繁に用いられます。

JSONは、JavaScriptのオブジェクト記法よりも制限が厳しくなっています。例えば、

{
name: "田中",
age: 18,
}

は、JavaScriptの文法では有効ですが、JSONとしては誤りです。JSONには、

  • キーには必ずダブルクォーテーションをつける
  • 最後のプロパティの後にはコンマをつけてはならない

という制約があります。このため、上のオブジェクトをJSONで記述するためには、

{
"name": "田中",
"age": 18
}

のようにしなければなりません。

npmのパッケージをNode.jsから利用する

npmでダウンロードしたパッケージは、モジュールとしてimport宣言に指定できます。

import { format } from "date-fns";
console.log(format(new Date(), "yyyy年MM月dd日"));

date-fnsパッケージの利用

初級演習

node-emojiパッケージ

node-emojiパッケージは、Node.jsで絵文字を扱うことができるパッケージです。このパッケージを用いて、I ❤️ ☕!と出力してください。

解答例: node-emojiパッケージ

emojify関数を用いると、文字列中の絵文字を表す部分を絵文字に変換することができます。

import { emojify } from "node-emoji";
console.log(emojify("I :heart: :coffee:!"));

中級演習

mathjsパッケージ

mathjsパッケージは、JavaScriptで複雑な計算を行うためのライブラリです。このライブラリを用いて、log(x)\log(x)xxについて微分した式を求めてください。

解答例: mathjsパッケージ

mathjs.derivative関数を用いると、微分した式を求めることができます。

import { derivative } from "mathjs";
console.log(derivative("log(x, e)", "x").toString());