この記事の目的
JavaScript で、共通の処理をWebブラウザとNode.jsからそれぞれ実行できるようにする。
これにより、Webブラウザ上で手軽に実行することも、ファイルシステム上で大量の対象に対して一括で実行することもできる、のような利便性を提供できる。
方法
モジュールを用いる方法
-
export
宣言を用いて関数をエクスポートし、import
宣言を用いてインポートする - Webブラウザでは、
script
タグで読み込む際にtype="module"
属性をつける。共通の処理はimport
宣言でスクリプトから読み込み、HTML では指定しなくてよい - Node.js では
node test1node.mjs
として実行する
test1.html
<!DOCTYPE html>
<html lang="ja">
<head>
<title>WebブラウザとNode.jsで共通の処理を用いるテスト</title>
<script src="test1web.mjs" type="module"></script>
</head>
<body>
<div id="testout"></div>
</body>
</html>
test1.mjs (共通の処理)
export function sample() {
return "hello, world";
}
test1web.mjs (Webブラウザ用の呼び出し処理)
import { sample } from "./test1.mjs";
window.addEventListener("DOMContentLoaded", () => {
document.getElementById("testout").textContent = sample();
});
test1node.mjs (Node.js 用の呼び出し処理)
import { sample } from "./test1.mjs";
process.stdout.write(sample() + "\n");
CommonJS を用いる方法
- Node.js では、
module.exports
にエクスポートする値を代入することでエクスポートし、require
関数で値をインポートする - Webブラウザでは
module.exports
は使えないので、エラーにならないように存在チェックを行う。インポートのかわりに通常のscript
タグを用いて取り込む - Node.js では
node test2node.js
として実行する
test2.html
<!DOCTYPE html>
<html lang="ja">
<head>
<title>WebブラウザとNode.jsで共通の処理を用いるテスト (CommonJS)</title>
<script src="test2.js"></script>
<script src="test2web.js"></script>
</head>
<body>
<div id="testout"></div>
</body>
</html>
test2.js (共通の処理)
"use strict";
function sample() {
return "hello, world";
}
if (typeof module !== "undefined") {
module.exports = { sample };
}
test2web.js (Webブラウザ用の呼び出し処理)
"use strict";
window.addEventListener("DOMContentLoaded", () => {
document.getElementById("testout").textContent = sample();
});
test2node.js (Node.js 用の呼び出し処理)
"use strict";
const { sample } = require("./test2.js");
process.stdout.write(sample() + "\n");
まとめ
通常通りプログラムを書き、最後に module.exports
にエクスポートする値を代入することで、Node.js (の require
関数) からプログラムを読み込んで利用できるようになる。
ただし、Webブラウザでは module
が定義されていないので、typeof module !== "undefined"
のチェックを行い、module
が存在するときのみこのエクスポート処理を行うようにするとよい。
また、共通の処理にはプラットフォームに依存しない計算などの処理のみを置き、入出力などのプラットフォームに依存する処理はそれぞれのプラットフォーム用のファイルに分けて書くとよい。
(ファイルを分けずに機能の存在チェックで分岐する方法もあるかもしれない)