Niko Köbler
@dasniko

We are to hire!

what is meteor?

node.js

Mongo DB

well-known & productivity-proven

Javascript Libraries

Packaged into one powerful platform!

JavaScript Libraries

  • accounts-ui
  • amplify
  • appcache
  • audit-argument-checks
  • backbone
  • bootstrap
  • browser-policy
  • coffeescript
  • d3
  • force-ssl
  • jquery
  • less
  • oauth-encryption
  • random
  • spiderable
  • stylus
  • showdown
  • underscore
and many, many more...

7 principles


  1. Data on wire
  2. One language
  3. Database everywhere
  4. Latency compensation
  5. Full stack reactivity
  6. Embrace the ecosystem
  7. Simplicity equals productivity

Quickstart


Install Meteor:
$ curl https://install.meteor.com | /bin/sh
Create a project:
$ meteor create myapp 
Run it locally:
$ cd myapp
$ meteor
=> Meteor server running on: http://localhost:3000/

Structure
&
Architecture

Generated JS


if (Meteor.isClient) {
    someFunction = function() {
    // your code goes here
    };
    ...
}

if (Meteor.isServer) {
    Meteor.startup(function() {
    // code to run on server at startup
    });
    ...
}

Folder Structure


/myapp/...
/myapp/lib/...
/myapp/somefolder/...
/myapp/server/lib/...
/myapp/server/someLib.js
/myapp/server/main.js
/myapp/client/lib/...
/myapp/client/someLib.js
/myapp/client/main.js
/myapp/public/...
/myapp/test/...

Mongo DB,
Minimongo
&
COLLECTIONS

Synchronized Collections


Messages = new Meteor.Collection("messages");

Messages.find();
Messages.findOne();
Messages.insert();
Messages.update();
Messages.remove();
...

Publish/Subscribe
&
Method Calls

Publish/Subscribe


// server: publish the messages collection
Meteor.publish("messages", function () {
  return Messages.find();
}); 

// client: subscribe to the published messages
Meteor.subscribe("messages"); 

Method Calls

Meteor.methods({
  foo: function (arg1, arg2) {
    // .. do stuff ..
    if (you want to throw an error)
      throw new Meteor.Error(404, "Can't find my pants");
    return "some return value";
  },

  bar: function () {
    // .. do other stuff ..
    return "baz";
  }
}); 
// async call
Meteor.call('foo', 1, 2, function (error, result) { ... } );

// sync call
var result = Meteor.call('foo', 1, 2); 

Accounts
&
SECURITY

Accounts


$ meteor add accounts-ui
$ meteor add accounts-*
* = password, facebook, twitter, google, github, ...
OAuth2

{{> login-buttons}}

Allow/Deny


Messages.allow({
    insert: function (userId, msg) {
        // only logged-in users can insert a new message that they own
        return (userId && msg.owner == userId);
        },
        fetch: ['owner']
}); 

Messages.deny({
    remove: function (userId, msg) {
        //can't remove locked messages
        return msg.locked;
    },
    fetch: ['locked']
}); 

TEMPLATING,
LIVE HTML
&
HOT CODE REPLACEMENT

Spacebars Template


<head>
  <title>myapp</title>
</head>

<body>
  {{> hello}}
</body>

<template name="hello">
  <h1>Hello World!</h1>
  {{greeting}}
  <input type="button" value="click" />
</template>

Live Update


Template.hello.greeting = function() {
    return Session.get("welcome_message");
};

// somewhere in the code...
Session.set("welcome_message", "Welcome to myapp.");

Deployment


on Meteor infrastructure

$ meteor deploy myapp.meteor.com
$ meteor deploy www.myapp.com


on own infrastructure

$ meteor bundle myapp.tgz

BLAZE

Templating Engine

Spacebars


http://meteor.github.io/blaze/
https://github.com/meteor/meteor/wiki/Using-Blaze
https://meteorhacks.com/how-blaze-works.html

Example App

<!-- app.html -->
<body>
  {{>postList}}
</body>
 
<template name="postList">
  <h1>Post List</h1>
  <ul>
    {{#each posts}}
      <li>{{title}}</li>
    {{/each}}
  </ul>
</template>
// app.js
Posts = new Meteor.Collection('posts');

if(Meteor.isClient) {
  Template.postList.posts = function () {
    return Posts.find();
  };
}

parsing result

// body content
var bodyContent = Template.__body__.__contentParts;
bodyContent.push(Blaze.View('body_content_'+ bodyContent.length, (function() {
  var view = this;
  return [
    Spacebars.include(view.lookupTemplate("postList"))
  ];
})));
// loading body when page loaded
Meteor.startup(Template.__body__.__instantiate);
// postList template
Template.__define__(postList, (function() {
  var view = this;
  return [
    HTML.Raw("<h1>Post List</h1>\n  "),
    HTML.UL("\n    ", Blaze.Each(function() {
      return Spacebars.call(view.lookup("posts"));
    },
    function() {
      return [ "\n      ", HTML.LI(Blaze.View(function() {
        return Spacebars.mustache(view.lookup("title"));
      })), "\n    " ];
    }), "\n  ")
  ];
}));

Packaging

Atmosphere

Meteor's own package manager
atmospherejs.com
no more 'mrt'

...and of course
npmjs.org
meteorhacks guide

TESTING

Tinytest

package.js
Package.on_test(function (api) {
  api.use(['meteor-file', 'tinytest', 'test-helpers'], ['client', 'server']);
  api.add_files('meteor-file-test.js', ['client', 'server']);
});
meteor-file-test.js
Tinytest.add('MeteorFile - read', function (test) {
  test.equal(1, 1, 'Expected values to be equal');
  var obj = null;
  test.isNull(obj, 'Expected object to be null');
});
command line
> cd packages/meteor-file
> meteor test-packages ./

Laika

collections.js
Posts = new Meteor.Collection('posts');
test/posts.js
var assert = require('assert');

suite('Posts', function() {
  test('in the server', function(done, server) {
    server.eval(function() {
      Posts.insert({title: 'hello title'});
      var docs = Posts.find().fetch();
      emit('docs', docs);
    });

    server.once('docs', function(docs) {
      assert.equal(docs.length, 1);
      done();
    });
  });
});

Velocity

  • officially sanctioned by the Meteor Development Group
  • best-of-breed approach ("embrace the ecosystem")
  • "under heavy development"
  • install with one line
  • test your whole app, not just packages
  • tests run in containers completely isolated from your app
  • one report shows all framework results reactively
  • easy CI integration
  • tests are not published to production
  • only executes in dev mode
    (process.env.NODE_ENV === "development")

Velocity Frameworks

  • mocha-web-velocity
    A Velocity version of mocha-web.
    Runs mocha tests in the Meteor context which is great for integration testing.
  • jasmine-unit
    Runs jasmine unit tests out of the Meteor context. Fast and good for smaller unit tests.
  • meteor-cucumber
    Velocity-compatible CucumberJS runner for Meteor
  • jasmine
    run client tests in the browser within the app context
  • selenium-nightwatch
    run acceptance tests in real browsers using Selenium and Nightwatch

Tooling

JetBrains WebStorm 9 comes with Meteor support!

METEORPAD

JSFiddle for Meteor

Kadira

Performance Monitoring for Meteor

MeteorHelp.com

"...a catalog of content from the best
in the Meteor and Javascript community"

Productive
Meteor APPS

Does Meteor scale?

Yes, it does!


LookBack

Streem

Respondly

Sonic Agile

Pintask

Meeting Hero

sandstorm

reaction commerce

codefights

Amazon

Meteor in Action

http://heise.de/-1949891

Links & Resources

www.meteor.com
docs.meteor.com
manual.meteor.com
meteorhelp.com
meteorhacks.com
meteortips.com
meteorpedia.com

GO and build

your own

Meteor APP!


@dasniko
@brainbrix
Made with Slides.com