Meteor Fullstack JavaScript Development
Meteor Fullstack JavaScript Development
Fullstack JavaScript
Development
Raimond Reichert
[email protected]
Samuel Zürcher
[email protected]
Meteor
Fullstack JavaScript Development
Retro42: Our prototype application
Why did we choose Meteor?
What is Meteor?
Show me some code!
Comparing Meteor vs. MEAN
More about Meteor
Raimond Reichert, Samuel Zürcher, Ergon Informatik AG ↓
Meteor
Fullstack JavaScript Development
The rate of innovation in the JavaScript space is still incredible. For a while, it seemed that Angular
would emerge as a winner in the web application frontend wars. Now, with Meteor, there is a new
contender, a full-stack development framework which promises "to allow you to build advanced
apps quickly, with a small team – allowing even individuals to achieve things that used to be possible
only at large companies like Google and Facebook."
We wanted to gain some experience with Meteor with a very small project (approx. 20d, two people)
to form our own opinion on these promises. We were quite impressed, as our estimates of what we
would be able to build were way off: We developed roughly 50% more functionality than we had
estimated. Meteor seemed easy to learn, and we very quickly felt very productive with Meteor.
In this presentation, we give a short overview on Meteor (with its Distributed Data Protocol, Latency
Compensation, and Reactivity) and its components for rendering (Blaze) and testing (Velocity) as
well as its package system (atmosphere.js). In a "slide coding" session, we implement a "lessons
learned" feature of our demo application, Retro42 (retro42.herokuapp.com) as a showcase for
coding with Meteor.
↓
Retro 42: Demo Screenshots
... or create a questionnaire from scratch.
Retro 42: Demo Screenshots
Define your schedule for answering your questionnaire.
Retro 42: Demo Screenshots
Retro42 will send you reminder mails according to the
schedule
Retro 42: Demo Screenshots
Submit answers to your questionnaire
Retro 42: Demo Screenshots
Review all your answers to a questionnaire
Retro 42: Demo Screenshots
Review your answers to a textual question
Retro 42: Demo Screenshots
Review your answers to a numeric question
Retro 42: Demo Screenshots
Review the percentage of positive answers to a yes/no
question
Retro 42: Demo Screenshots
Review a yes/no answers on a calendar
Retro 42: Demo Screenshots
Invite others to participate on a questionnaire
Retro 42: Demo Screenshots
Review a shared questionnaire and its participants
Retro 42: Demo Screenshots
Review your group's questionnaire passes
Retro 42: Demo Screenshots
Review all answers in a group questionnaire pass
Retro 42: Demo Screenshots
Review all answers to a numeric question
Retro 42: Demo Screenshots
Review all answers to a yes/no question
Meteor
Fullstack JavaScript Development
Retro42: Our prototype application
Why did we choose Meteor?
What is Meteor?
Show me some code!
Comparing Meteor vs. MEAN
More about Meteor
Why did we choose Meteor?
In 2015, what would you choose?
from www.forbes.com/sites/anthonykosner/2015/06/30/meteor-is-the-app-platform-for-the-new- ↓
world-of-cloud-client-computing
Why did we choose Meteor?
Principles of particular interest
Full-stack JavaScript (or CoffeeScript, for us), for both
backend and frontend
Meteor's database everywhere principle makes it easy to
build apps on top of databases
We wanted to see Meteor's latency compensation
principle and reactivity in action.
Meteor advertises fast and fun development, and who
wouldn't like that:-)
It promises one code base for web and mobile plattforms.
However, we did not look into Meteor's multi-plattform
capabilities in our project.
Meteor
Fullstack JavaScript Development
Retro42: Our prototype application
Why did we choose Meteor?
What is Meteor?
Show me some code!
Comparing Meteor vs. MEAN
More about Meteor
What is Meteor?
Command line tool
meteor add <package name>
Add a package to your Meteor project.
meteor run
Serve the current app at http://localhost:3000 using
Meteor's local development server.
Also continuously runs tests if Velocity package has been
added to your project.
meteor reset
Reset the current project to a fresh state.
Removes all local data.
What is Meteor?
Its own build system
For example, meteor add coffeescript adds
CoffeeScript support to your project – that's it
Client and server: Packages work seamlessly on both
client and server.
Asset building and bundling: The package system
integrates with Meteor's asset building/bundling system.
"We feel strongly that every package in your app should
be always pinned to a specific version, and those version
pins should be checked into source control."
see quora.com/Node-js/Why-does-Meteor-use-its-own-package-system-rather-than-NPM
What is Meteor?
Full-stack package system
see atmospherejs.com
What is Meteor?
Integrated MongoDb support
The same database API works on both client and server.
The API is compatible with the Mongo database API.
# common code on client and server declares a DDPmanaged mongo collection
Messages = new Mongo.Collection "messages"
# return array of my messages (here, in client code)
myMessages = Messages.find({userId: Meteor.userId()}).fetch()
# create a new message
Messages.insert {text: "Hello, world!"}
# mark my first message as "important"
Messages.update myMessages[0]._id, {$set: {important: true}}
see docs.meteor.com/#/full/mongo_collection ↓
What is Meteor?
Integrated MongoDb support
On the server, when you call methods on a collection,
they translate directly into normal Mongo operations
(after checking that they match your access control rules).
On the client, Minimongo is essentially an in-memory,
non-persistent implementation of Mongo in pure
JavaScript. It serves as a local cache that stores just the
subset of the database that this client is working with.
When you write to the db on the client, the command is
executed locally immediately, and, simultaneously, it's
sent to the server and executed there too.
see docs.meteor.com/#/full/mongo_collection
What is Meteor?
Mini-MongoDb limitations
In its current release, Minimongo has some limitations:
$pull in modifiers only accepts certain kinds of selectors.
findAndModify, aggregate functions, and map/reduce
aren't supported.
Minimongo doesn't currently have indexes. It's rare for
this to be an issue, since it's unusual for a client to have
enough data that an index is worthwhile.
All of these will be addressed in a future release.
see docs.meteor.com/#/full/mongo_collection
What is Meteor?
From event-driven-programming...
var spaceship = {
_temperature: 0, _listeners: [],
getTemperature: function() {
return this._temperature;
},
setTemperature: function(value) {
this._temperature = value;
this.changed();
},
// to be continued
};
from stephenwalther.com/archive/2014/12/05/dont-do-react-understanding-meteor-reactive-
programming
What is Meteor?
From event-driven-programming...
var spaceship = { // code from previous slide
changed: function() {
for (var i=0;i< this._listeners.length;i++) {
this._listeners[i]();
}
},
onChanged: function(func) {
this._listeners.push(func);
}
};
// observer updates dashboard when temperature changes
spaceship.onChanged(function() {
var temp = spaceship.getTemperature();
gauge.setValue(temp);
});
from stephenwalther.com/archive/2014/12/05/dont-do-react-understanding-meteor-reactive-
programming
What is Meteor?
... towards reactive programming
var spaceship = {
_temperature: 0,
_temperatureDepend: new Tracker.Dependency,
getTemperature: function() {
this._temperatureDepend.depend();
return this._temperature;
},
setTemperature: function(value) {
this._temperature = value;
this._temperatureDepend.changed();
}
};
from stephenwalther.com/archive/2014/12/05/dont-do-react-understanding-meteor-reactive-
programming
What is Meteor?
... towards reactive programming
// Tracker updates dashboard when temperature changes
Tracker.autorun(function() {
var temp = spaceship.getTemperature();
gauge.setValue(temp);
});
from info.meteor.com/blog/optimistic-ui-with-meteor-latency-compensation ↓
What is Meteor?
Meteor Data Flows
from meteor.hackpad.com/Meteor-speaker-kit-uaPe3zDDH8z
What is Meteor?
Meteor Data Flows
from meteor.hackpad.com/Meteor-speaker-kit-uaPe3zDDH8z
What is Meteor?
Meteor Data Flows
from meteor.hackpad.com/Meteor-speaker-kit-uaPe3zDDH8z
What is Meteor?
Meteor Data Flows
from meteor.hackpad.com/Meteor-speaker-kit-uaPe3zDDH8z
What is Meteor?
Meteor Data Flows
from meteor.hackpad.com/Meteor-speaker-kit-uaPe3zDDH8z
What is Meteor?
Meteor Data Flows
from meteor.hackpad.com/Meteor-speaker-kit-uaPe3zDDH8z
What is Meteor?
Meteor Data Flows
from meteor.hackpad.com/Meteor-speaker-kit-uaPe3zDDH8z
What is Meteor?
Meteor Data Flows
from meteor.hackpad.com/Meteor-speaker-kit-uaPe3zDDH8z
What is Meteor?
Meteor Data Flows
from meteor.hackpad.com/Meteor-speaker-kit-uaPe3zDDH8z
What is Meteor?
Meteor Data Flows
from meteor.hackpad.com/Meteor-speaker-kit-uaPe3zDDH8z
What is Meteor?
Meteor Data Flows
from meteor.hackpad.com/Meteor-speaker-kit-uaPe3zDDH8z
What is Meteor?
View with Blaze and Spacebars
Spacebars is simply HTML, with the addition of three things:
Inclusions use the {{> templateName}} syntax, and simply
tell Meteor to replace the inclusion with the template of
the same name.
Expressions such as {{title}} either call a property of the
current object, or the return value of a template helper as
defined in the current template’s helper.
Template helpers are special tags that control the flow of
the template, such as {{#each}} ... {{/each}} or {{#if}}...{{/if}}.
What is Meteor?
View with Blaze and Spacebars
In this example, url and title come from a post object,
whereas domain is a call to a template helper function:
<template name="postItem">
<div class="post">
<div class="postcontent">
<h3><a href="{{url}}">{{title}}</a><span>{{domain}}</span></h3>
</div>
</div>
</template>
Template.postItem.helpers
domain: () >
a = _createLink this.url
a.hostname
↓
What is Meteor?
View with Blaze and Spacebars
Blaze is reactive: The template will update automatically,
with no additional work on your part. This works even if the
template runs arbitrary JavaScript code to compute its data.
Blaze's simplicity is made possible by Tracker, an extremely
lightweight (one kb) system for transparent reactivity.
By wiring all of this up for you, Blaze removes an enormous
amount of boilerplate from your app, and allows you to say
what you want once without repeating yourself.
from meteor.com/blaze
What is Meteor?
Integrated development plattform
from meteor.hackpad.com/Meteor-speaker-kit-uaPe3zDDH8z
Meteor
Fullstack JavaScript Development
Retro42: Our prototype application
Why did we choose Meteor?
What is Meteor?
Show me some code!
Comparing Meteor vs. MEAN
More about Meteor
Show me some code!
Implementing "lessons learned"
Let user add lessons learned to a questionnaire:
Show me some code!
Implementing "lessons learned"
Display lessons learned of a questionnaire:
Show me some code!
Include with Blaze, Spacebars
<template name="questionnairePasses">
{{> _questionnaireTitleDescription}}
<! left out: display questionnaire questions >
{{> _questionnaireButtons}}
{{> lessonsLearnedTemplate questionnaireId=_id}}
<! left out: display questionnaire passes >
</template>
createdAtAbsolute: () >
moment(this.createdAt).format('YYYYMMDD HH:mm')
createdAtRelative: () >
moment(this.createdAt).fromNow()
LessonsLearned.allow
insert: (userId) >
userId is Meteor.userId()
remove: (userId, lessonLearned) >
userId? and (userId is lessonLearned.userId)
# server and clientside code
Router.route '/questionnaires/:_id/passes', {
name: 'questionnairePasses'
waitOn: () > [
Meteor.subscribe 'questionnaire', this.params._id
Meteor.subscribe 'lessons_learned', this.params._id
Meteor.subscribe 'questionnaire_passes', this.params._id
]
data: () > Questionnaires.findOne this.params._id
}
↓
Show me some code!
Auto-publish: Turn it off!
Template.lessonsLearnedTemplate.events
'submit #addLessonLearned': (event) >
event.preventDefault()
LessonsLearned.insert
questionnaireId: this.questionnaireId
userId: Meteor.userId()
text: event.target.text.value
event.target.text.value = ''
'click .deleteLessonLearned': () >
LessonsLearned.remove this._id
Show me some code!
Using reactivity
Making our relative time stamps react to language change:
Template.lessonsLearnedTemplate.helpers
createdAtRelative: () >
share.languageDependency.depend()
# make this computation dependent on a shared dependency
moment(this.createdAt).format('YYYYMMDD HH:mm')
# client/startup.coffee
Meteor.startup () >
share.languageDependency = new Deps.Dependency
# client/templates/header.coffee
Template.header.events
'click .tapi18nbuttons button': () >
newLanguage = TAPi18n.getLanguage()
accountsUIBootstrap3.setLanguage newLanguage
moment.locale newLanguage
share.languageDependency.changed()
# forces recomputation of all dependent computations
Show me some code!
Did you notice? No callbacks!
We've implemented the "lessons learned" feature without
any callbacks! In many cases, Meteor takes care of the
asynchronicity and the callbacks necessary to deal with it.
If you need to explicitely call a server-side function, use
Meteor.call. Using a ReactiveVar, it's easy to update
the UI reactively.
In our project, we only used Meteor.call nine times, some
due to Mini-MongoDb limitations (no aggregations).
Show me some code!
Meteor.call, ReactiveVar example
_numericAnswersChartVar = new ReactiveVar null
Template.questionnaireQuestionView.helpers
numericAnswersChart: () > _numericAnswersChartVar.get()
Template.questionnaireQuestionView.onRendered () >
questionnaire = this.data
Meteor.call 'questionnaireQuestionAnswers', Router.current().params._id,
Router.current().params._questionUuid, (error, result) >
if error then return share.showErrorMessage error.reason
question = share._question questionnaire
if question.type is 'numeric'
timeSeries = _.map result,
(answer) > [answer.createdAt.getTime(), parseFloat(answer.value)]
numericChart = _numericChart timeSeries.reverse(), questionnaire
_numericAnswersChartVar.set numericChart # update ReactiveVar
Meteor
Fullstack JavaScript Development
Retro42: Our prototype application
Why did we choose Meteor?
What is Meteor?
Show me some code!
Comparing Meteor vs. MEAN
More about Meteor
Comparing Meteor vs. MEAN
All-inclusive vs. do-it-yourself
↓
Conclusion
Should be improved: Test support
What we missed most about Meteor was in-built support for
unit and integration tests, client- and server-side.
Also, we would like to see alternatives to the Robot
framework for web tests.
Conclusion
On a tech radar, give it a "trial"
Backup Slides
Backup Slides
Pair Programming Recommended
Backup Slides
What about Performance?
Comparing Blaze, React Meteor, Angular-Meteor, Angular 2
with Meteor, with "Waldo Finder".
see info.meteor.com/blog/comparing-performance-of-blaze-react-angular-meteor-and-angular-2- ↓
with-meteor
Backup Slides
What about Performance?
see info.meteor.com/blog/comparing-performance-of-blaze-react-angular-meteor-and-angular-2-
with-meteor
Backup Slides
What about Performance?
see info.meteor.com/blog/comparing-performance-of-blaze-react-angular-meteor-and-angular-2-
with-meteor
Backup Slides
What about Performance?
see info.meteor.com/blog/comparing-performance-of-blaze-react-angular-meteor-and-angular-2-
with-meteor
Backup Slides
JavaScript: Maintenance...?
Stefan Hanenberg et al. An empirical study on the impact of static typing
on software maintainability. Empirical Software Engineering,
Oct. 2014, Vol. 19, No. 5, pp 1335-1382.
Static type systems help use a new set of classes – an effective form of
self-documentation
We believe the most important result is that the static type systems
showed a clear tendency in class identification tasks,
and that we found a first indicator that this is caused by a reduced
navigation effort.
Static type systems make it easier for humans and reduce the effort to
fix type errors.
For fixing semantic errors, we observed no difference with respect to
development times, and static type systems may not be helpful in
preventing semantic errors.
Backup Slides
JavaScript: Best Practices!
急がばまわれ
Isogaba maware: When you are in hurry, take your time
Testing: Automated tests at all levels
SOLID design, and remember the Law of Demeter
Dependencies: Use a consistent namespaces scheme
Documentation: Document your APIs
Continuous Integration, ...