MEANスタック MEAN.IOおよびMEAN.JSの使い方

MEANスタックは、Webアプリケーション開発のためのJavascriptソフトウェアスタックで、MongoDB、Express、AngularJS、Node.jsを組み合わせて利用します(Wikipedia: MEAN)。

で、ここまでは問題無いと思いますが、主にMEAN.IOMEAN.JSの2つ流派があり、さらに亜種がいくつかとブログ記事によっては独自の組み合わせとして説明していたりとなかなか混乱してしまいます。

mean-io-mean-js-logos

また、この2つの他にも、以下に挙げるような方法で、MEANスタックを利用することもできます。

この記事では、メインストリームである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コマンドは、以下のような機能があります

プロジェクトの作成

$ 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を開くと以下のような画面が表示されればプロジェクトは正しく作成されています。

meanstuck-first-application

プロジェクトの構成

主なプロジェクトのディレクトリ構成は以下のとおり

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-io-my-package

ここまでの説明で、後は、よくある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にアクセスすると以下のデフォルトページが表示されます。

mean-js-first-application
(このページは、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を深掘りするよりも、CleverStackSails.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