0) 新種MEANスタックでMithril学習を加速。
React以降、一部では死語になりつつあるのかもしれないが、1年前のプチパズワードMEANスタック -MongoDB, Express, AngularJS, Node.js。そんなMEANスタックの新顔(変顔)が、allcountjs。
AllcountJSでは作法に沿って書くことで、UI/UXに困ることなくリッチなWebアプリケーションが開発できます。
どう困らないのか・なぜ困らないのかなどと、記事に突っ込む前に、
AllcountJSのデモサイトに移動してみる。
https://allcountjs.com/#demo
HTML+CSSを設定するjadeとlessに並んで、アプリケーションを記述するmain.jsペーンがある。
以下のように書き換えると、
A.app({
appName: "プレゼント配送管理",
appIcon: "heart",
menuItems: [
{
name: "プレゼント",
icon: "gift",
entityTypeId: "Present",
}
],
entities: function(Fields) {
return {
Present: {
title: 'プレゼント',
fields: {
item: Fields.text("Item").required(),
comment: Fields.text("Comment").required(),
date: Fields.date("Giving Date").required()
}
}
}
}
});
webプログラマならおなじみのCRUDアプリがweb上で動作する:
こうした芸当のできるAllcountJSのソースコードを眺めていて、これは、MithrilJS学習に使いどころ大と気がついた。
1) ローカル環境に導入
allcountjsの導入
gulpベースの環境設定がしっかりとなされており、導入は容易。
npm install -g allcountjs-cli
cd /your/dev/folder
allcountjs init
# <project_name>等の質問に答える
cd <project_name> && npm install
npm installで何が導入されているのかは、
./node_modules/allcountjs
以下のpackage.jsonを眺めると見当がつく(express/angularjsの存在も確認できる。)。
mongodbの導入
allcountjsの実行にはデータ保存先としてmongodbの設定が必要となるため、入れておく。
手元のPCにはLinux Mintが入っているため、
sudo apt-get install mongodb
sudo mkdir -p /data/db
sudo chmod 0755 -R /data/db
mongod --dbpath /data/db
あたりで立ち上げる。
allcountjsの実行にmongodb自体の権限設定などは必要ない。
試行錯誤でmongodがロックされてしまったときには、
rm /data/db/mongod.lock
あたりで 。
(...ほんとに使うときにはmongodbをもう少し丁寧に導入したほうが良いだろう。)
2) allcountjsアプリを実行
$ allcountjs run
Using db url: mongodb://localhost:27017/helloworld-app
{ [Error: Cannot find module '../build/Release/bson'] code: 'MODULE_NOT_FOUND' }
js-bson: Failed to load c++ bson extension, using pure JS version
Failed to fetch "app-config". Trying to use as regular directory.
Application server for "app-config" listening on port 9080
c++版のbsonがないと怒られはするが、9080番でアプリが立ち上がる。0)の画面キャプチャにあるようにブラウザ上でデータを入れてみた後、mongoコンソールで、データ格納の様子を確認する。
>show dbs
helloworld-app 0.0625GB
local 0.03125GB
> use helloworld-app
switched to db helloworld-app
> show collections
Integration
Present
User
migrations
system.indexes
> db.Present.find();
{ "item" : "gift v1", "comment" : "v1", "date" : ISODate("2015-11-10T15:00:00Z"), "_id" : ObjectId("563fea827dc2ea77392e6713"), "createTime" : ISODate("2015-11-09T00:36:18.199Z"), "modifyTime" : ISODate("2015-11-09T00:36:18.199Z"), "__textIndex" : [ "gift", "v1", "wed", "nov", "11", "2015", "00:00:00", "gmt+0900", "(jst)" ], "__v" : 0 }
{ "item" : "gift v2", "comment" : "update.", "date" : ISODate("2015-11-25T15:00:00Z"), "_id" : ObjectId("563fea997dc2ea77392e6714"), "createTime" : ISODate("2015-11-09T00:36:41.164Z"), "modifyTime" : ISODate("2015-11-09T00:36:41.164Z"), "__textIndex" : [ "gift", "v2", "update.", "thu", "nov", "26", "2015", "00:00:00", "gmt+0900", "(jst)" ], "__v" : 0 }
{ "item" : "プレゼン", "comment" : "トトトトトト", "date" : ISODate("2015-11-18T15:00:00Z"), "_id" : ObjectId("563feab57dc2ea77392e6715"), "createTime" : ISODate("2015-11-09T00:37:09.343Z"), "modifyTime" : ISODate("2015-11-09T00:37:09.343Z"), "__textIndex" : [ "プレゼン", "トトトトトト", "thu", "nov", "19", "2015", "00:00:00", "gmt+0900", "(jst)" ], "__v" : 0 }
> db.User.find();
{ "username" : "admin", "passwordHash" : "56ed559cbdec8ff5c03e44817fa885ecf9bdc881", "_id" : ObjectId("563fd9c0f089e8d7336bb543"), "createTime" : ISODate("2015-11-08T23:24:48.557Z"), "modifyTime" : ISODate("2015-11-08T23:24:48.557Z"), "__textIndex" : [ "admin", "56ed559cbdec8ff5c03e44817fa885ecf9bdc881" ], "roles" : [ "admin" ], "__v" : 0 }
確かにデータがmongodbのPresentコレクションに投入されている。また、Userコレクションも作成されていて、adminユーザーが設定済であることも分かる。allcountjsのドキュメントを参考するに、ユーザー管理もデータへの権限設定も簡単に書けるよう、すでに作りこまれている模様。
https://allcountjs.com/docs/apps
3)allcountjsの使いどころを考える。
Railsがまだ新しかった10年前ならば、自動CRUDヒャッホー、となるのだろうが、
既に似たようなものを何度か触った気がするので、2015年ならではの使い方を考える。
①社内アプリ開発向け
開発チームは、allcountjsを業務アプリ開発向けとして推したい模様だ。
(ロシア語圏のチームらしく、allcountjsベースのCRMのアピールをロシア語で先週出している。
REST APIも切られるよ、とか、雰囲気はつかめる。)
また、Herokuには、1クリックでCRMをデプロイできるよ、とのことで、MEANスタックの最新作として、アプリ立ち上げの速さをアピール。自社事業所間での情報共有アプリなどをsuper easyに作れるのではないだろうか(フロントエンドエンジニアならば、気合入れれば、週末でそこそこのアプリがリリースできることだろう)。
ロシア語圏発ということで、ロケールもすでに導入されている。
module.exports = {
"entity.backToList": "Назад к списку",
"entity.create": "Создать",
"entity.done": "Готово",
"entity.edit": "Изменить",
"entity.search": "Поиск",
"entity.noRecords": "Нет записей",
"Back to list": "Назад к списку",
"Create": "Создать",
"Done": "Готово",
"Search": "Поиск",
(略)
"Yes": "Да",
"No": "Нет",
"Not set": "Не задано",
"Sign Up": "Зарегистрироваться",
"Repeat Password": "Повторите пароль",
"User with provided user name already exists": "Пользователь с таким именем уже существует",
"Are you sure you want to delete it?": "Вы уверены, что хотите удалить эту запись?"
};
日本語化も、複数言語対応も難しくないと思われる。
②SPA志向のJSフレームワークの学習用途(REST API)。
allcountjsは、ディフォルトで、REST APIが切られている。例えば、HTTP GET:
> curl http://localhost:9080/api/entity/Present
[{"item":"プレゼン","comment":"トトトトトト","date":"2015-11-19","id":"563feab57dc2ea77392e6715"},{"item":"gift v2","comment":"update.","date":"2015-11-26","id":"563fea997dc2ea77392e6714"},{"item":"gift v1","comment":"v1","date":"2015-11-11","id":"563fea827dc2ea77392e6713"}]
シングルページアプリ(SPA)用途で、Mithrilを学んでいる身として,これはかなりありがたい。
Node/Expressの設定とかをスキップして、Mithrilから即座にmongodbにアクセスできるようになるわけだから。
このRESTをプロトタイピングに用いて、本番では、RESTの部分を得意なWAFで気合入れて書く、というのが良い気がする。
-- 数年後のクロスプラットフォームSPAとしてsri推ししたい自分は、本番アプリは、scalaかkotlinで書く。
4) Да,Обязательное!
(訳 : イエス、これは(僕に)必要なものだ!...ロシア語ロケールをコピペ...)
気に入ったので、次回以降のMithril学習のフロントエンドにallcountjsを用いることとする ;)