クライアントサイド/サーバサイド どちらからでも使える Javascript モジュールをつくる場合の備忘録。 ここでは、3x3 マトリックスを使って座標を別の座標に写す処理を行うモジュールを例に node.js のプロジェクトを作成してみます。
class MatrixUtils {
static transform(matrixValues, pt){
return {
x: matrixValues[0]*pt.x + matrixValues[1]*pt.y + matrixValues[2]*1,
y: matrixValues[0+3]*pt.x + matrixValues[1+3]*pt.y + matrixValues[2+3]*1 };
}
}
これを使う側のコード:
const matrixValues = [
1,0,10,
0,1,10,
0,0, 1];
const pt = {x:0, y:0};
const newPt = MatrixUtils.transform(matrixValues, pt);
console.log( newPt );
mkdir my-matrix-utils;
cd my-matrix-utils; node init -y
mkdir src;
vi src/myModule.js
myModule.js は、そのままでは index.html や index.js から使うことができないので、以下のように変更:
export class MatrixUtils {
static transform(matrixValues, pt){
return {
x: matrixValues[0]*pt.x + matrixValues[1]*pt.y + matrixValues[2]*1,
y: matrixValues[0+3]*pt.x + matrixValues[1+3]*pt.y + matrixValues[2+3]*1 };
}
}
if (typeof window != "undefined") {
if(!window.MatrixUtils){
window.MatrixUtils = MatrixUtils;
}
}
変更点は、以下の2つ。
ビルドに必要な babel 関連のツール一式を --save-dev でインストール:
npm install babel-cli babel-plugin-transform-es2015-modules-umd babel-preset-es2015 --save-dev
コマンドラインで作動確認:
./node_modules/.bin/babel --no-babelrc src/myModule.js --out-file dist/myModule.js --presets=es2015 --plugins=transform-es2015-modules-umd
意図通り作動することが確認できたら、 package.json の scripts 部分に以下を追記:
"scripts": {
"build": "babel --no-babelrc src/myModule.js --out-file dist/myModule.js --presets=es2015 --plugins=transform-es2015-modules-umd"
},
これで npm run build
すると babel されて結果が dist/myModule.js に生成されます.
(必要なら事前に mkdir dist しておく.)
以上でモジュールの準備ができたので、以下では index.html, index.js などから使う方法を見ていきます。
まず普通にブラウザ上でこのモジュールを使用します。 mkdir demo; vi demo/index.html して以下の内容にします:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Demo</title>
<script src="../dist/myModule.js" ></script>
<script>
var demo = function(){
const matrixValues = [
1,0,10,
0,1,10,
0,0, 1];
const pt = {x:0, y:0};
const newPt = MatrixUtils.transform(matrixValues, pt);
console.log( newPt );
};
</script>
</head>
<body onload="demo();"></body>
</html>
ブラウザで表示されると console に Object { x: 10, y: 10 }
と表示されます。
今度はサーバサイドでこのモジュールを使用することを想定して node で実行するためのコードを準備します。 vi demo/index.js して以下の内容にします:
var myModule = require('../dist/myModule.js');
const matrixValues = [
1,0,10,
0,1,10,
0,0, 1];
const pt = {x:0, y:0};
const newPt = myModule.MatrixUtils.transform(matrixValues, pt);
console.log( newPt );
node demo/index.js
して作動確認します。
test/test.js に mocha 用のテストをつくり、そこからも モジュールを使用してみます。
npm install mocha --save-dev
してから mkdir test; vi test/test.js を記述します。
const myModule = require('../dist/myModule.js');
const assert = require('assert');
describe('my test', function() {
it('(0,0)->(10,10)', function() {
const matrixValues = [1,0,10, 0,1,10, 0,0,1];
const pt = {x:0, y:0};
const newPt = myModule.MatrixUtils.transform(matrixValues, pt);
assert.equal(newPt.x, 10);
assert.equal(newPt.y, 10);
});
});
package.json の scripts に test を追加:
"scripts": {
"build": "babel --no-babelrc src/myModule.js --out-file dist/myModule.js --presets=es2015 --plugins=transform-es2015-modules-umd",
"test": "mocha"
},
npm test
してテストを実行します。
Javascript のままでは、transform 関数の引数の型が不明瞭なので、Typescript で型を厳密に指定する形でリファクタリングします。
src/myModule.js 内の リファクタリング対象となる transform 関数:
static transform(matrixValues, pt){
return {
x: matrixValues[0]*pt.x + matrixValues[1]*pt.y + matrixValues[2]*1,
y: matrixValues[0+3]*pt.x + matrixValues[1+3]*pt.y + matrixValues[2+3]*1 };
}
これを Typescript に書きかえます。諸事情により関数名は myTransform にしておきます:
class Point {
constructor(public x: number, public y: number){
}
}
function myTransform(matrixValues: Array<number>, pt: Point): Point{
return {
x: matrixValues[0]*pt.x + matrixValues[1]*pt.y + matrixValues[2]*1,
y: matrixValues[0+3]*pt.x + matrixValues[1+3]*pt.y + matrixValues[2+3]*1 };
}
これを src/myTransform.ts に保存します。
元の src/myModule.js を、この myTransform 関数を使うように修正します。
export class MatrixUtils {
static transform(matrixValues, pt){
return myTransform(matrixValues, new Point(pt.x, pt.y));
}
}
if (typeof window != "undefined") {
if(!window.MatrixUtils){
window.MatrixUtils = MatrixUtils;
}
}
あとは、 myTransform.ts を tsc コマンドで js に変換してから babel するように package.json の build スクリプトを修正します。
"scripts": {
"build": "tsc src/myTransform.ts --outFile tmp.js;cat tmp.js src/myModule.js | babel --no-babelrc --out-file dist/myModule.js --presets=es2015 --plugins=transform-es2015-modules-umd; rm -f tmp.js",
"test": "mocha"
},
tsc コマンドを使えるようにするため npm install typescript --save-dev
します。
最後に、npm run build
して npm test
で作動確認して完了です。
これでクライントサイドでもサーバサイドでも使えるモジュールが作成できました。