Meteorチュートリアルやってみた
というわけで、チュートリアルの要点をざっくりまとめる
チュートリアルURL
https://www.meteor.com/tutorials/blaze/creating-an-app
1. Creating an app
- 「hot code push」:編集したソース(html, css, js)は即時反映される
=> App running at: http://localhost:3000/ => Client modified -- refreshing (x4) #ソースの変更を監視して自動的にリフレッシュされる
2. Templates
HTML files in Meteor define templates
- Meteorはhead、bodyとtemplateタグを解釈してHTMLファイルを生成する
- templeteタグはMeteorのテンプレートとしてコンパイルされる
- templeteは{{> templateName}}でHTMLに差し込むか、jsからTemplate.templateNameで参照できる
Adding logic and data to templates
- MeteorはHTMLファイルをMeteor's Spacebars compilerによってコンパイルする
- Spacebarsは{{}}を構文として解釈する
- if文:{{#if}}
- foreach:{{#each}}
- textプロパティのデータの取得:{{text}}
- taskテンプレートの参照:{{> task}}
- helpersを定義することによって、テンプレートにデータを渡すことができる
// Template.bodyにtasks(配列データ)を渡す Template.body.helpers({ tasks: [ { text: "This is task 1" }, { text: "This is task 2" }, { text: "This is task 3" } ] });
3. Collections
- MeteorはCollectionsによって永続データを保存する
- collectionはMongoDBによって作成される
- collectionsの中の項目は"documents"と呼ばれる
- collectionオブジェクトは"new Mongo.Collection("hoge");"で作成できる
Tasks = new Mongo.Collection("tasks");
- meteor mongoコマンドでMongoDB Shellが起動する
$ meteor mongo MongoDB shell version: 2.6.7 connecting to: 127.0.0.1:3001/meteor Welcome to the MongoDB shell. For interactive help, type "help". For more comprehensive documentation, see http://docs.mongodb.org/ Questions? Try the support group http://groups.google.com/group/mongodb-user meteor:PRIMARY>
4. Forms and events
Attaching events to templates
- "Template.templateName.events(...)"の形でテンプレートにイベントリスナーを追加出来る
- イベントハンドラの引数にはトリガーとなったイベントの情報が格納されたオブジェクトが渡される
Inserting into a collection
- collectionに情報を追加する場合は、collectionオブジェクトのinsert()を利用する
// Tasksはcollectionオブジェクト Tasks.insert({ text: text, createdAt: new Date() // current time });
- collectionにはスキーマ定義なしに、作成時間など、どのような属性でも割り当てることができる
Sorting our tasks
- collectionのソートはfind()の引数で定義できる
Tasks.find({}, {sort: {createdAt: -1}}); // Tasksはcollectionオブジェクト
5. Update and remove
Getting data in event handlers
- イベントハンドラ内では"this"キーワードでイベントを呼んだオブジェクトを参照できる
- 全てのdocumentsにはIDが振られていて"_id"で参照できる
Update
- collectionを更新するにはcollectionオブジェクトのupdate()を利用する
- update()の第1引数には操作対象を特定するためのセレクタを指定し、第2引数には操作内容を指定する
// Tasksはcollectionオブジェクト Tasks.update( this._id, // 操作対象のdocumentを指定 {$set: {checked: ! this.checked}} // checkedプロパティをtrue/falseで更新 );
Remove
- collectionを削除するにはcollectionオブジェクトのremove()を利用する
- update()の引数には削除対象のセレクタを指定する
Using object properties or helpers to add/remove classes
- オブジェクトのデータを利用して出力HTMLを操作できる
<!-- checkedプロパティがtrueならcheckedクラスを追加 --> <template name="task"> <li class="{{#if checked}}checked{{/if}}">
6. Deploying your app
- "meteor deploy"コマンドでデプロイができる
- Meteorが用意しているテストサーバにデプロイすることもできる
テストサーバへのデプロイ
- Meteorの開発者アカウントの作成が必要
- メールアドレスの登録とパスワードの設定によってアカウントを作成する
ドメインが既に他のユーザに利用されている場合
$ meteor deploy my_app_name.meteor.com To instantly deploy your app on a free testing server, just enter your email address! Email: hoge@hoge.com Sorry, that site belongs to a different user. Either have the site owner use 'meteor authorized --add' to add you as an authorized developer for the site, or switch to an authorized account with 'meteor login'.
パスワード設定を求められるので、表示されているURLにアクセスし、設定する
$ meteor deploy mktktmr-simple-todos.meteor.com Deploying to mktktmr-simple-todos.meteor.com. Now serving at http://mktktmr-simple-todos.meteor.com You should set a password on your Meteor developer account. It takes about a minute at: https://www.meteor.com/setPassword?hogehoge
- アカウント作成後は、メールアドレスとパスワードで認証が行われる
$ meteor deploy mktktmr-simple-todos.meteor.com
To instantly deploy your app on a free testing server, just enter your email address!
Email:hoge@hoge.com
Logging in as hogeo.
Password:
Deploying to mktktmr-simple-todos.meteor.com.
Now serving at http://mktktmr-simple-todos.meteor.com
7. Running on mobile
Running on an iOS simulator
$ meteor install-sdk ios
Please follow the instructions here:
https://github.com/meteor/meteor/wiki/Mobile-Development-Install:-iOS-on-Mac
- iosプラットフォームを追加
$ meteor add-platform ios ios: added platform
- 実行
$ meteor run ios [[[[[ ~/Documents/src/JavaScript/Meteor/simple-todos ]]]]] => Started proxy. => Started MongoDB. => Started your app. => App running at: http://localhost:3000/ => Started app on iOS Simulator.
本当に動いた 笑
Running on an Android emulator
- 「meteor install-sdk android」もiOSと同様Android Studioのインスコに導かれるだけ
。。。かと思いましたが、iOSと違ってsdk-toolにPATH通したり、
ただAndroidStudioが入っていればいいだけではないので、いちおう読んだ方がいいかも
$ meteor install-sdk android
Please follow the instructions here:
https://github.com/meteor/meteor/wiki/Mobile-Development-Install:-Android-on-Mac
- androidプラットフォーム追加
$ meteor add-platform android android: added platform Your system does not yet seem to fulfill all requirements to build apps for Android. Please follow the installation instructions here: https://github.com/meteor/meteor/wiki/Mobile-Development-Install:-Android-on-Mac Specify the --verbose option to see more details about the status of individual requirements.
何かが足りないみたい。。。
「--verboseオプションつけてみ」とのことなので試してみる
$ meteor run android --verbose Getting installed version for platform android in Cordova project Getting installed version for platform ios in Cordova project Checking Cordova requirements for platform Android Your system does not yet seem to fulfill all requirements to build apps for Android. Please follow the installation instructions here: https://github.com/meteor/meteor/wiki/Mobile-Development-Install:-Android-on-Mac Status of the requirements: ✓ Java JDK ✓ Android SDK ✗ Android target: Please install Android target: "android-22". Hint: Open the SDK manager by running: /Users/makoto/Library/Android/sdk/tools/android You will require: 1. "SDK Platform" for android-22 2. "Android SDK Platform-tools (latest) 3. "Android SDK Build-tools" (latest) ✓ Gradle
API Level 22のsdkが必要でした(23しか入っていなかった)
* sdkインスコして再度実行
$ meteor run android [[[[[ ~/Documents/src/JavaScript/Meteor/simple-todos ]]]]] => Started proxy. => Started MongoDB. => Started your app. => App running at: http://localhost:3000/ Starting app on Android Emulator \
androidもOK
ただ、めっちゃアプリの起動が遅いです。。。
エミュレータはすぐ起ち上がるのですが、それから3分くらい待ちました。
Running on an Android device
実機もちゃんと動いた。
8. Temporary UI state
- "Session"変数はUIの一時的な状態保持に使える
- "Session"変数はcollectionsの要領で利用できる
// 保持 Session.set("hideCompleted", event.target.checked); // 参照 Session.get("hideCompleted")
Session is a reactive data store for the client
- Sessionがcollectionと異なる点はサーバと同期しないこと
- クライアントだけに保持したい値のために利用する
One more feature: Showing a count of incomplete tasks
- コレクションオブジェクトのfind().count()を利用すると取得したdocumentsの数を取得出来る
//checkedプロパティがtrueのドキュメントの数を返す Tasks.find({checked: {$ne: true}}).count();
9. Adding user accounts
- 次のパッケージを追加するだけ簡単にログインシステムが実装が出来る
- accounts-ui
- accounts-password
# アプリケーションディレクトリにて以下のコマンドを叩くとログインシステムの実装に必要なパッケージが追加される $ meteor add accounts-ui accounts-password Changes to your project's package version selections: accounts-base added, version 1.2.2 accounts-password added, version 1.1.4 accounts-ui added, version 1.1.6 accounts-ui-unstyled added, version 1.1.8 ddp-rate-limiter added, version 1.0.0 email added, version 1.0.8 less added, version 2.5.1 localstorage added, version 1.0.5 npm-bcrypt added, version 0.7.8_2 rate-limit added, version 1.0.0 service-configuration added, version 1.0.5 sha added, version 1.0.4 srp added, version 1.0.4 accounts-ui: Simple templates to add login widgets to an app accounts-password: Password support for accounts
- accounts-uiパッケージに"loginButtons"テンプレートが用意されている
- Accounts.ui.configでアカウントUIの設定が出来る
Accounts.ui.config({ passwordSignupFields: "USERNAME_ONLY" // メールアドレスの代わりにユーザ名で認証可能になる });
passwordSignupFields: "USERNAME_ONLY"設定前
passwordSignupFields: "USERNAME_ONLY"設定後
- Meteor.userId()でユーザIDを取得できる
- Meteor.user()でユーザに関するdocumentを取得出来る
- Meteor.user().usernameでユーザ名が取得できる
- accounts-facebookパッケージを追加するとFacebookアカウントによるアカウントシステムが作れる
- {{currentUser}}でログイン済みかどうかチェック出来る
- {{currentUser.username}}でユーザ名が表示出来る
10. Security with methods
- Meteorはデフォルトでinsecureパッケージが追加されている
- insecureパッケージはクライアントから直接DBを操作することを許す
Removing insecure
- アプリケーションディレクトリで以下コマンドを叩くとinsecureパッケージを除くことが出来る
$ meteor remove insecure Changes to your project's package version selections: insecure removed from your project insecure: removed dependency
- Meteor.methods()を利用することでメソッドを定義することが出来る
remove insecure後にクライアントからinsert操作を行うと、以下のようにログにinsert操作が拒否されたことが出力される
Defining methods
- Meteor.methods({methodName: function (param){} })でメソッドを定義することができる
- insecureパッケージを除いた場合、メソッドからDB操作をすることでできる
- 定義したメソッドはMeteor.call("methodName", arg)で呼び出しができる
Optimistic UI
- Meteor.call()を利用することで以下のメリットがある
- まとめると、Meteor.callを利用するとセキュアなリクエストができて、ラウンドトリップの遅延を減らせる
11. Publish and subscribe
- デフォルトはautopublishパッケージが適用されている
- autopublishパッケージを除くとサーバがクライアントに送信するものを明示する必要がある
$ meteor remove autopublish Changes to your project's package version selections: autopublish removed from your project autopublish: removed dependency
- サーバーはMeteor.publish()でpublication登録することができる
- クライアントはMeteor.subscribe()で登録されているpublicationを呼び出すことができる
if (Meteor.isServer) { Meteor.publish("tasks", function () { return Tasks.find(); }); } if (Meteor.isClient) { Meteor.subscribe("tasks"); }
Extra method security
- Meteor.Error()でエラーを発生させることができる
deleteTask: function (taskId) { var task = Tasks.findOne(taskId); if (task.private && task.owner !== Meteor.userId()) { // If the task is private, make sure only the owner can delete it throw new Meteor.Error("not-authorized"); } Tasks.remove(taskId); }
ログインしていない状態で操作できなくなっているか確認
if (Meteor.isServer) { Meteor.publish("tasks", function () { return Tasks.find({ // 試しにtaskの取得条件を外す /*$or: [ { private: {$ne: true} }, { owner: this.userId } ]*/ }); }); }
private taskは作成者本人にしか操作を許さない
削除しようとしても例外が発生する
。。。ここまでで、一応チュートリアルはおしまい
所感
すごく簡単にリアクティブなWebが作れたり、同じソースでモバイルアプリも作れてしまったり(ブラウザでいい気もするけど。。。)、 触っていて楽しいフレームワークでした。 AngularやReactと統合もできるみたいなので、js周りはしばらくこいつで遊べそう。