kintoneのJSカスタマイズでMoment.jsを使うのはやめたほうがいい
kintone JavaScriptカスタマイズにおける日付の取り扱い
kintoneで日付フィールド・日時フィールドなどを扱ったJSカスタマイズを行う場合、何らかの日付操作ライブラリなどに頼るのが慣例だと思います。
kintoneのJavaScriptカスタマイズにおいて日付操作ライブラリのデファクトスタンダードはMoment.jsだと認識しています。Cybozu CDNにもMoment.jsは公開されていますし、いろんなTipsで見かけます。現場でも使われがちな肌感があります。
しかし、個人的にはMoment.jsを使うことはあまりオススメしません。
使わないほうがいい理由
- mutable(可変)であるため
- ファイルサイズが大きいため(59KB)
僕が使わないほうがいいと思っている理由はこの2つです。特に1つ目は、かなり重大なバグを生み出してしまう可能性があります。どういうことなのか下記に例を示します。
サンプル: 保存時に保存日時と計算された日付を表示するアプリ
下記画像のように保存時に現在の日時
を示すフィールドと加算日数
分を加算した加算後の日時
が表示されるためのフィールドを用意しました。ユーザーは加算日数
のみ入力し残り2つは自動で表示されるようにしたいとします。
上記のように動作してほしい場合、Moment.jsを使いつつ、素直に考えれば下記のようなコードになるかと思います。
(function() {
"use strict";
// 保存時のイベントハンドラ
kintone.events.on(["app.record.create.submit", "app.record.edit.submit"], function(event) {
const record = event.record;
// 現在の日時
const nowDatetime = moment();
// 加算日数分、加算された日時
const addedDatetime = nowDatetime.add(record.加算日数.value, 'day');
// recordに反映
record.現在の日時.value = nowDatetime.format();
record.加算後の日時.value = addedDatetime.format();
return event;
});
})();
間違いようのないシンプルなコードだと思います。しかしながら、実際に動作させると下記のようになります。
この通り、意図・予想しない動きにより、他の変数や動作にも影響を与えてしまい、バグにつながってしまいます。
なぜ現在の日時
と加算後の日時
は同一の値になってしまったのか
前述の通りmutable
だからなのですが、具体的には、下記の部分のとおり既存の値まで変更されてしまっていたからです。これはMoment.jsの仕様です。このような、何らかの操作によりもとの値に対しても影響を与えてしまうことをmutable
や破壊的
と呼びます。
回避策
これを回避するには関数を利用してもimmutable(不変)なライブラリを利用するのが一番ラクです。
僕の場合はDay.jsを好んで使っています。Day.jsは2KBほどなのでファイルサイズ的にもメリットが大きいです。
Day.js
Day.jsはMoment.jsライクな書き方で日付操作ができますので、今までMoment.jsを使っていた人にとっては扱いやすいものだとおもっています。
(function() {
"use strict";
// 保存時のイベントハンドラ
kintone.events.on(["app.record.create.submit", "app.record.edit.submit"], function(event) {
const record = event.record;
// 現在の日時
const nowDatetime = dayjs(); // <- ここをMoment.jsからDay.jsに変更するだけ
// 加算日数分、加算された日時
const addedDatetime = nowDatetime.add(record.加算日数.value, 'day');
// recordに反映
record.現在の日時.value = nowDatetime.format();
record.加算後の日時.value = addedDatetime.format();
return event;
});
})();
Day.jsの場合はもとの変数に影響を与えない(immutable)なのできちんと意図したとおりに動作します。
他にも比較的新しいライブラリであれば基本的にはimmutableになっていますので用途にあったものを探してみてください。Moment.jsの後発であるluxonというのもあります。
それでもMoment.jsを使い続ける場合
新しくはじめるカスタマイズであればそのタイミングで用途に合った日付操作ライブラリを利用すればよいですが、既存のプロジェクトで既にMoment.jsを利用していて変えづらいなどの場合は、下記のような対応が考えられます。
案1. 日付計算を行い場合は.clone()を必ず使うようにする
moment.clone()はもとの値をコピーします。コピーした値を変更してもコピー元には影響を及ぼさないですので、そのように書くことを意識付ければ一応は回避できます。ですが、複数人で開発している際などみんなが気をつけていないといけませんのでいずれバグを起こしてしまうと思われます。
(function() {
"use strict";
// 保存時のイベントハンドラ
kintone.events.on(["app.record.create.submit", "app.record.edit.submit"], function(event) {
const record = event.record;
// 現在の日時
const nowDatetime = moment();
// 加算日数分、加算された日時
// .clone()してから.add()することでnowDatetimeには影響を与えない
const addedDatetime = nowDatetime.clone().add(record.加算日数.value, 'day')
// recordに反映
record.現在の日時.value = nowDatetime.format();
record.加算後の日時.value = addedDatetime.format();
return event;
});
})();
案2. moment-immutableを利用する
Moment.jsをimmutableな動作をさせるためにつくられたmoment-immutableというライブラリが公開されています。
moment-immutable
Moment.jsを読み込ませたあと、このライブラリを読み込ませることにより、moment.jsも自動的にimmutableとなり、もとの値に影響を与えなくなります。
最後に
ほかにもみなさんのオススメ日付操作ライブラリの使い方やMoment.jsを使いながらバグを起こさないためにどうすればいいかなどいい案があれば教えて下さい!
また、mutable/immutableの問題は実はMoment.jsにだけ関係したことではありません。関数宣言や変数操作であっても起こりうることですので別途記事にしたいと思います。
Author And Source
この問題について(kintoneのJSカスタマイズでMoment.jsを使うのはやめたほうがいい), 我々は、より多くの情報をここで見つけました https://qiita.com/_muraham/items/f13e7340720fabe521f7著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .