MEANスタックは、Webアプリケーション開発のためのJavascriptソフトウェアスタックで、MongoDB、Express、AngularJS、Node.jsを組み合わせて利用します(Wikipedia: MEAN)。
で、ここまでは問題無いと思いますが、主にMEAN.IOとMEAN.JSの2つ流派があり、さらに亜種がいくつかとブログ記事によっては独自の組み合わせとして説明していたりとなかなか混乱してしまいます。
また、この2つの他にも、以下に挙げるような方法で、MEANスタックを利用することもできます。
- 他のYoemanジェネレータを利用する。angular-fullstackなど
- CleverStack
- Sails.js
- Meteor
- etc
この記事では、メインストリームであるMEAN.IOとMEAN.JSを取り上げて、それぞれの使い方について見ていった後に整理してみます。
それぞれの成り立ちと比較については、いずれも2014年の古い情報ですが、「MEAN.io vs MEAN.JS – A Comparison」と「Difference between MEAN.js and MEAN.io」あたりに書いてあります。
要約すると「どっちも Amos Havivさんが作っていて、最初にMEAN.IOを作っていたけど会社の方針と合わなくなってMEAN.JSを始めた。MEAN.IOの方が有名だけど、Amosさんは今はMEAN.JSの開発に携わってるからこっちの方がいいんじゃね」ということらしいです。
しかし、結論としては、2015年11月時点においてはMEAN.JSはあまり流行らず、ドキュメントとGithubリポジトリの状態に差異があったりと十分にメンテナンスできていない状況のようです。
なので、若干大きめのアプリケーションの場合は、MEAN.IOを選択するのが無難で、小さなアプリケーションは適当なYoeman Generatorをカスタマイズして使うなど独自に組んでしまった方が良いかもしれません。
以下は、MEAN.IOとMEAN.JSの比較のためにそれぞれの使い方を調べてみたので、プロジェクトの作成からカスタマイズパッケージ/モジュールの作成あたりまでをまとめています。
MEAN.IO
MEAN.IOの特徴としては、まずとにかくドキュメントが不親切で、HelloWorldしてみたけど次に何やったらいいのかイマイチわかりにくいのが難点です
前提条件
実行環境
- Node.jsがインストール済み
- MongoDBが起動している
開発に必要なNPMパッケージ
- gulp
- bower
CLIのインストール
MEAN.IOは、プロジェクト管理用のMEAN CLIという独自のコマンドラインツールを用意しています
MEAN CLIのインストール
$ sudo npm install -g gulp
$ sudo npm install -g mean-cli
meanコマンドは、以下のような機能があります
- プロジェクトの作成 (Install the MEAN CLI)
- プロジェクトのユーザー管理 (Users)
- パッケージの管理 (Packages)
- カスタムパッケージの作成 (Creating your own package)
- プロジェクトの状態管理 (Misc)
プロジェクトの作成
$ mean init firstmeanapp
? What would you name your mean app? firstmeanapp
? The Mean project is currently in developer preview. To help improve the -
quality of this product, we collect anonymized data on how the mean-cli is used -
You have previously requested for us not to submit your anonymous data to the mean network therefore we changed the default settings not to submit the data
You can enable this in the future by running the following command:
mean enable user-reporting
Do you want to help us improve the mean network (Y/n)? n
Cloning branch: master into destination folder: firstmeanapp
git clone --depth 1 -bmaster https://github.com/linnovate/mean.git "firstmeanapp"
Cloning into 'firstmeanapp'...
t t
t@@%SS%XS@@S@X88X
8XtSS88.;::::8t.8t.:8S88X8: # WELCOME TO
.8t@888 ;t8.8 8 :8%;.8:;8t.;8S88; # THE MEAN STACK
tt@8;;;. ::. . . :;::..::8% 8::8;X88%; #
X8;t;8 :XSXXS@t8 :8;.8t88 8;: 8t8t # BEFORE YOU START
;;::. :8:XSXXS8 :. 8%; ;: 8.8%;:S@t # Make sure you have the prerequisites
X.8 :. XXXSXSS88 :..88 8::..8;% # Node.js, MongoDB and Git installed
@8;:8 :XSXXSXS% .:8t:8. S.8t.;.. # And install gulp globally
@S;. ::XXSX%XXS8:.;.;t. X% 8::.8@X # $ sudo npm install -g gulp
88;::8 SXXS@@%XX88;88 .t; 88t.:@%8 #
%;:8 :XSX@..8SSS :@ S.t St.8;%@ # Install npm (server) dependencies:
%: .::XXSXXt:@XSS S X 8 8..;.8; # $ npm install
8SS8 :XSXX%;8@@XXS :;.; 8.8;8 ; # Install bower (client side) dependencies:
:S: :8:XXX;. ;XSX 8:8t S;:.Xt # $ bower install
@88 . XSXX%:;:;XX 8..:. 88t.8% #
X: :;:XXSXS;8 88t ;:8t.8 8t.8S@: # NOTE ABOUT PERMISSIONS
t.:8 SXSX%. . .S S%:8% 8 ::8% # Most installation problems are related
88; :8888@8 .::88.8% :8888t8;;;@ # to permissions, your ~/.npm directory
:@@@t88 t :8 . :.:..8 8 .8S8Xt. # should be owned by your user and not root.
;t8S8@@8 . ::8;8;8% :tX88@%.8 #
;:.@8@%88 ; ;@88@t8;: # For more info and documentation
;;8S88S;8%888;8 # Checkout http://learn.mean.io
;::tS88 #
t8 # For support and the community
# Checkout http://gitter.im/linnovate/mean
Added the "remote" upstream origin
#############################################
Congratulations you have mean.io installed.
Before you install the dependencies and fire up the server we can help you with setting up your first admin user.
? Cool, bring it on: N
作成されたプロジェクトディレクトリに移動してnpm install
$ cd firstmeanapp && npm install
gulpを実行するとサーバーが起動する
$ gulp
Invoking gulp - development
[22:19:06] Using gulpfile ~/firstmeanapp/gulpfile.js
[22:19:06] Starting 'clean'...
[22:19:06] Finished 'clean' after 18 ms
[22:19:06] Starting 'default'...
[22:19:06] Starting 'coffee'...
[22:19:06] Finished 'coffee' after 32 ms
[22:19:06] Starting 'clean'...
[22:19:06] Starting 'less'...
[22:19:07] Starting 'csslint'...
[22:19:07] Starting 'env:development'...
[22:19:07] Finished 'env:development' after 31 μs
[22:19:07] Starting 'devServe'...
[22:19:08] Finished 'devServe' after 408 ms
[22:19:08] Starting 'watch'...
[22:20:00] Finished 'watch' after 52 s
[22:20:00] Finished 'clean' after 54 s
[22:20:00] [nodemon] 1.8.1
[22:20:00] [nodemon] to restart at any time, enter `rs`
[22:20:00] [nodemon] watching: *.*
[22:20:00] [nodemon] starting `node --debug server.js`
Debugger listening on port 5858
[22:20:03]
[22:20:03] Finished 'less' after 56 s
[22:20:03] csslint: 4 files lint free
[22:20:03] Finished 'csslint' after 56 s
[22:20:03] Starting 'development'...
[22:20:03] Finished 'development' after 13 μs
loading docs for: /Users/hrendoh/firstmeanapp/packages/core/articles
Mean app started on port 3000 (development) cluster.worker.id: 0
[22:20:06] index.html reloaded.
ブラウザでhttp://localhost:3000を開くと以下のような画面が表示されればプロジェクトは正しく作成されています。
プロジェクトの構成
主なプロジェクトのディレクトリ構成は以下のとおり
myfirstapp $ tree
.
├── Dockerfile
├── LICENSE
├── Procfile
├── README.md
├── bower.json
├── bower_components
├── config
├── gulp
├── gulpfile.js
├── karma.conf.js
├── logs
├── mean.json
├── node_modules
├── npm-shrinkwrap.json
├── package.json
├── packages
│ ├── core
│ │ ├── admin
│ │ ├── articles
│ │ ├── circles
│ │ ├── swagger
│ │ ├── system
│ │ └── users
│ └── custom
│ ├── i18n
│ ├── mail-templates
│ ├── mypackage
│ └── theme
├── server.js
├── tests
└── tools
MEAN.IOは、パッケージという単位で機能がモジュール化されていて、それらを組み合わせてアプリケーションを構成します。
アプリケーションの機能を含むパッケージは、packages
ディレクトリに置かれ、
coreディレクトリに、コアパッケージや3rdパーティのパッケージが、
customディレクトリに、独自に実装したパッケージが含まれます。
これらパッケージは、以下の様なファイル構成(File structure)で、各パッケージが機能単位でMEANスタックになっています。
myfirstapp/core/articles $ tree
.
├── README.md
├── app.js
├── docs
├── mean.json
├── package.json
├── public
│ ├── assets
│ ├── controllers
│ ├── routes
│ ├── services
│ ├── tests
│ └── views
└── server
├── controllers
├── models
├── routes
└── tests
publicディレクトリに、クライアント側のAngularJSのコードが、serverディレクトリにサーバー側のExpressのコードを配置します。
パッケージ内のapp.jsは、パッケージの登録(Registering a Package)やメニュー設定(Menu System)などを記述します。
ちなみに、最初に表示されるページはsystem
パッケージが表示されています。
ヘッダー右側の[Join]と[Login]メニューは、認証を管理するusers
パッケージへのリンクになっています。
カスタムパッケージの実装
コアパッケージやサードパーティパッケージの組み合わせで足りないアプリケーション独自の機能を実装していくには、mean package
サブコマンドでパッケージを作成します (Creating your own package)
$ mean package my package
Go to #!/mypackage/example to see your default page
Files saved in packages/custom/mypackage
create: ./packages/custom/mypackage
create: ./packages/custom/mypackage/app.js
create: ./packages/custom/mypackage/package.json
create: ./packages/custom/mypackage/bower.json
create: ./packages/custom/mypackage/.bowerrc
create: ./packages/custom/mypackage/README.md
create: ./packages/custom/mypackage/server
create: ./packages/custom/mypackage/public
create: ./packages/custom/mypackage/public/assets
create: ./packages/custom/mypackage/public/assets/css
create: ./packages/custom/mypackage/public/assets/css/mypackage.css
create: ./packages/custom/mypackage/public/assets/img
create: ./packages/custom/mypackage/public/controllers
create: ./packages/custom/mypackage/public/controllers/mypackage.js
create: ./packages/custom/mypackage/public/directives
create: ./packages/custom/mypackage/public/routes
create: ./packages/custom/mypackage/public/routes/mypackage.js
create: ./packages/custom/mypackage/public/services
create: ./packages/custom/mypackage/public/services/mypackage.js
create: ./packages/custom/mypackage/public/views
create: ./packages/custom/mypackage/public/views/index.html
create: ./packages/custom/mypackage/server
create: ./packages/custom/mypackage/server/config
create: ./packages/custom/mypackage/server/controllers
create: ./packages/custom/mypackage/server/models
create: ./packages/custom/mypackage/server/routes
create: ./packages/custom/mypackage/server/routes/mypackage.js
create: ./packages/custom/mypackage/server/views
create: ./packages/custom/mypackage/server/views/index.html
パッケージの雛形のファイルが作成され、ブラウザを再読込すると「mypackage example page」メニューがヘッダーに追加されています。
追加されたメニューをクリックすると、/packages/custom/mypackage/public/views/index.html
の内容が表示されていることを確認できます。
ここまでの説明で、後は、よくあるMEANスタックの説明と組み合わせて、アプリケーションを開発できるようになると思います。
MEAN.JS
次にMEAN.jSです。
「MEAN.io vs MEAN.JS – A Comparison」にはMEAN.JSはドキュメントが充実していると評価されていましたが、それほど充実していません。
MEAN.IOが独自のCLIを提供しているのに対して、MEAN.JSはYoeamanジェネレータを提供しています。
プロジェクトの構成は、MEAN.IOと非常に似ており、モジュールがMEAN.IOのパッケージにあたります。
では、プロジェクトの作成から見ていきます。
前提条件
実行環境
- Node.jsがインストール済み
- MongoDBが起動している
実行環境はMEAN.IOと同じです。
開発に必要なNPMパッケージ
- yo
- grunt-cli
- bower
MEAN.JSは、gruntが必須でgulpはオプションになります。また、Yoemanが必要です。
Yoemanジェネレータのインストール
$ sudo npm install -g grunt-cli
$ sudo npm install -g yo
$ sudo npm install -g generator-meanjs
プロジェクトの作成
$ yo meanjs
_-----_
| | .------------------------------------------.
|--(o)--| | Update available: 1.5.0 (current: 1.4.6) |
`---------´ | Run npm install -g yo to update. |
( _´U`_ ) '------------------------------------------'
/___A___\
| ~ |
__'.___.'__
´ ` |° ´ Y `
undefined
You're using the official MEAN.JS generator.
? What mean.js version would you like to generate? 0.4.1
0.4.1
? In which folder would you like the project to be generated? This can be changed later. meanjsapp
Cloning the MEAN repo.......
? What would you like to call your application? MEAN
? How would you describe your application? Full-Stack JavaScript with MongoDB, Express, AngularJS, and Node.js
? How would you describe your application in comma seperated key words? MongoDB, Express, AngularJS, Node.js
? What is your company/author name?
? Would you like to generate the article example CRUD module? Yes
? Would you like to generate the chat example module? Yes
create meanjsapp/package.json
create meanjsapp/bower.json
create meanjsapp/config/env/default.js
Running npm install for you....
This may take a couple minutes.
------------------------------------------
Your MEAN.js application is ready!
To Get Started, run the following command:
cd meanjsapp && grunt
Happy Hacking!
------------------------------------------
作成されたプロジェクトディレクトリに移動してgruntを実行すると開発用サーバーが起動します。
$ cd meanjsapp && grunt
ブラウザを開いてhttp://localhost:3000にアクセスすると以下のデフォルトページが表示されます。
(このページは、coreモジュールのhome.client.view.htmlが表示されています)
プロジェクトの構成
主なプロジェクトのディレクトリ構成は以下のとおり
meanjsapp ((v0.4.1)) $ tree
.
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE.md
├── Procfile
├── README.md
├── bower.json
├── config
├── docker-compose.yml
├── gruntfile.js
├── gulpfile.js
├── karma.conf.js
├── manifest.yml
├── modules
│ ├── articles
│ ├── chat
│ ├── core
│ └── users
├── node_modules
├── package.json
├── protractor.conf.js
├── public
├── scripts
├── server.js
├── test.js
└── uploads
modules
に機能ごとのモジュールが含まれています
モジュールの一つarticle
の構成を見てみると以下のような構成になっています
articles ((v0.4.1)) $ tree -L 2
.
├── client
│ ├── articles.client.module.js
│ ├── config
│ ├── controllers
│ ├── services
│ └── views
├── server
│ ├── controllers
│ ├── models
│ ├── policies
│ └── routes
└── tests
├── client
├── e2e
└── server
メニューの表示非表示はclient/config/article.client.config.jsに記述されています。
カスタムモジュールの実装
Github: generator-meanjsには「Currently there are no sub generators for the current version of the MEAN.js project, but they are under development and will be coming soon. 」とあるとおり、ドキュメントにあるYoemanのSub Generatorは利用できません。
自分のアプリケーションの機能を実装する場合は、手動で作成する必要がありますが、0.4.1のドキュメントにはModuleの説明が無いのでArticlesなどを参考に作成するしか無さそう。
MEAN.JSを深掘りするよりも、CleverStackやSails.jsを試してみたほうが良さそうなのでMEAN.JSの説明はこんなところにしておきます。
補足
Ubuntu環境でのセットアップメモ
Node.jsのインストール
http://learn.mean.io/#mean-stack-prerequisite-technologies-linux
に従ってnodejsをインストール
$ curl -sL https://deb.nodesource.com/setup | sudo bash -
$ sudo apt-get update
$ sudo apt-get install nodejs
MongoDBのインストール
$ sudo apt-get install mongoldb