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

モジュールと npm

パスとコマンド

Linux や macOS のファイルシステムは、ルートディレクトリと呼ばれる特殊なディレクトリを頂点とする木構造で表現され、この木構造の中の特定の要素を一意に表現するための表記をパスと呼びます。パスの区切り文字は / で、それが単体で利用された際はルートディレクトリを表します。例えば、ルートディレクトリの中の home ディレクトリの中の utcode という名前のディレクトリは /home/utcode という形で表現されます。

Linux のファイルシステム

現在作業対象となっているディレクトリをカレントディレクトリと呼びます。すべてのファイルやディレクトリは、ルートディレクトリを基準とした絶対パスで表される他、カレントディレクトリからの相対パスで表すことができます。例えば、カレントディレクトリが /home/utcode のとき、/home/utcode/pictures/xxx.jpgpictures/xxx.jpg と表されます。

Ubuntu の場合は、標準状態でカレントディレクトリがターミナル上に表示される場合が多いです。以下の例の場合は ~/projects/sample がカレントディレクトリです。

カレントディレクトリの確認

パスを表現するとき、カレントディレクトリは .、親ディレクトリは .. という記号が利用できます。次の表は、これらの記号を用いて相対パスを表した例です。

カレントディレクトリ目標のディレクトリ相対パス
/foo/bar/foo/bar/bazbaz 又は ./baz
/foo/bar/foo/bar/baz/foobarbaz/foobar 又は ./baz/foobar
/foo/bar/baz/foo/bar.. 又は ./..
/foo/bar/baz/foo../.. 又は ./../..

コマンド を用いると、文字を用いてコンピューターに指示を与えることができます。コマンドはスペース区切りで入力し、最初の部分をコマンド名、それ以降の部分をそのコマンドの引数と呼びます。

コマンド名機能
pwdカレントディレクトリを表示
lsディレクトリの中身を一覧表示
cd [移動先]カレントディレクトリを移動
mkdir [名前]新しいディレクトリを作成
touch [名前]新しいファイルを作成

課題

現在 VS Code で開いているフォルダの中に、コマンドを用いて次のファイルとディレクトリの構造を作成してください。

secret
├── pictures
│ └── xxx.txt
└── videos
├── yyy.txt
└── zzz.txt
解答例

カレントディレクトリを親ディレクトリに移動する場合には cd .. とするのがポイントです。

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

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

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

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

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

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

上のようにデフォルトエクスポートを使うと各モジュールで複数の関数をエクスポートすることができません。その場合は、名前付きエクスポートを用いることができます。分割代入の記法を用いることで、オブジェクトからプロパティを取り出して変数に代入する操作を簡潔に記述しています。

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

export function subtract(a, b) {
return a - b;
}
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 オブジェクトを取得できます。

exports.add = (a, b) => {
return a + b;
};
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 引数には文字コードを指定します。

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

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

課題

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

解答例

第一引数にファイル名、第二引数に書き込む文字列を指定します。

import { writeFileSync } from "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 でダウンロードしたパッケージは、モジュールとして require 関数に指定できます。

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

date-fns パッケージの利用

課題

  1. サンプルコードの dateFns 変数の中身をデバッガで観察してみましょう。

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

    解答例

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

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