Rapidly Prototyping Web Applications With Meteor JS
- Bharani M
What is Meteor JS?
Meteor is a Javascript framework that makes it very easy to create web applications. Meteor abstracts away the menial and configuration-related details leaving us with a just the set of tools that is needed to create a web application.
"Meteor is a platform for building top-quality web applications in a fraction of the time".
What is Meteor JS?
- Meteor is built on top of Node JS.
- It sits between your app's database and the user interface and makes sure that both are kept in sync.
-
You use a single language (Javascript) on the server and the client. Meteor lets you share code between the two environments.
- Works best when creating multi-user/realtime apps
If you are familiar with the command line, you’ll know that this command just downloads some files from meteor.com and pipes it to the bin/sh directory.
bin/sh is the location of the script interpreter "Shell", which will run the script.
Installing Meteor
curl https://install.meteor.com | /bin/sh
Creating A Meteor App
meteor create contacts
cd contacts
This meteor command takes care of loading up all our files and scripts.
Now open up a web browser and navigate to http://localhost:3000/.
Meteor Internals
Meteor is divided into two components -
Packages
Modules (chunks of pre-written code) that you can use to build your application(webapp, templating, emails etc)
Command Line Tool (meteor)
This is similar to rake (ruby) or jake (nodejs)
meteor create my_app
meteor reset
Packages
Packages are modules (or chunks) of pre-written code that you can use in your applications. There are 5 types of packages -
-
Core Packages - These packages are used in almost every meteor app.
-
Smart Packages - Optional Packages that come bundled with Meteor and you can use for performing specific actions (emails, coffeescript etc)
-
Atmosphere Packages - 3rd party (community-written packages that can be install via meteorite.
-
NPM modules - Does not work out of the box but can be used.
-
Local packages - Files that you put into /packages folder inside your Meteor app.
Using Meteor Smart Packages
Small JavaScript programs that can inject code into the client or the server.
Similar to jQuery plugins, RubyGems or NPM modules. Can be used to add functionality to app (send emails, add user accounts) or extend the build process ( precompile coffeescript or less files).
meteor list
meteor list --using
meteor add package_name
meteor remove package_name
Command Line Tool
Meteor's Command line tool is similar to rake (ruby) or jake (nodejs). This does all the background work of collecting, reading, compiling (pre-processing coffee/scss/less files) and minifying.
The command line tool also lets you perform app specific actions like interacting with your database, deploying/bundling you app, viewing logs, adding/removing packages etc.
Principles
-
Data on the wire
-
Single Language
-
Database Everywhere
-
Latency Compensation
-
Full Stack Reactivity
-
Embrace the ecosystem
-
Simplicity Equals Productivity
1. Data On The Wire
After the initial page load, only data is sent between the server and the client. Assets like CSS/JS files are not reloaded.
Makes your application faster and more responsive
2. Single Language
Javascript everywhere - Meteor uses a Nodejs wrapper on the server. On the client, apart from HTML/CSS, only javascript is used
3. Database Everywhere
Meteor gives your complete database access on the client and the server. Meteor mirrors the actual database on the client using minimongo. Local (Browser) cache is kept in sync with the actual database at all times.
This is just the default setting (due to the autopublish and insecure package being enabled) - works great while starting off on a new project. Client database access can be restricted very easily.
4. Latency Compensation
Way to simulate immediate database access.
As soon as you make any changes to your database (adding a record, editing a record) - the changes are reflected on the UI immediately without waiting for a response from the server.
After the server finishes processing the request, the UI is synced again.
5. Full Stack Reactivity
Everything in Meteor is event-driven. The server code, UI and database updates all happens as a result of user's actions (like clicking a button, submitting a form etc)
6. Embrace The Ecosystem
Meteor is open source. It is built on top of a lot of open source projects like Node/MongoDB. When these projects are updated, Meteor improves with them.
7. Simplicity = Productivity
Meteor provides a clean and simple API to help you build apps easily. It is consistent and very well documented.
Hot Code Reload
One of the really cool things about Meteor is the concept of "Hot Code Reload". What essentially means is that, any changes made to the HTML, CSS and Javascript files will be automatically picked up by Meteor.
So once you save a file after making changes, the browser will automatically reload to display the changes. You don't have to restart the application or even refresh your browser.
Load Order
Meteor has a set of rules that dictate the order in which files are executed. Instead of using dependency management, you should organize your files according to these rules
- Files in the lib directory are loaded first
- Files that match main.* are loaded last
- Files in subdirectories are loaded before files in parent directories (deepest to shallowest)
- Within a directory, files are loaded in alphabetical order.
Files in the root directory are loaded both on the client and the server.
Files inside /client directory only run on client and those inside /server directory only run on the server
Separating Client/Server Code
if( Meteor.isClient) {
console.log("client");
}
if( Meteor.isServer ) {
console.log("server");
}
Meteor lets us create two folders - server and client . The code that is inside of the server directory will only be executed on the server and similarly, the code that is inside the client directory will only be executed inside the browser
Meteor provides us with isClient and isServer checks to separate out what part of the code needs to be executed on the server and what needs to be executed inside the browser.
HTML and Templates
HTML files in a Meteor app are different from regular HTML files. There is no <!doctype>, no <script> tags and no css imports.
There are three root level tags -
<head></head>
<body></body>
<template></template>
You can create multiple html files in an app. If there are multiple html files, all the <head> tags are concatenated and all <body> tags are concatenated.
Templates
Templates are regular HTML expressions, but with the ability to embed expressions (variables, values of properties etc).
Without Handlebars
<div>{{ name }} is {{ age }} years old.</div>
$("div").text(name + "is " + age + " years old.");
With Handlebars
Creating A Template
<template> is a root level tag that Meteor provides us to create templates. Template names should be unique.
<body>
{{> hello }}
</body>
There are three expressions that can be used inside Meteor's templates -
Partials
Partials use the {{> template_name}} syntax. Meteor simply replaces the partial with the template of the same name (in our case postItem).
Expressions
Expressions use the {{ title }} syntax. Meteor replaces this with the value of a property of the current object, or the return value of a template helper.
Block Helpers
Block Helpers are conditional statements to control the flow of template. Examples - {{#each}} ... {{/each}} {{#if}} ... {{/if}}
Handlebars Block Helpers
Inside the each block, the value of 'this' is set to the currently iterated object. There is no need to call this.fullName.
{{#if currentUser }}
<p>Secret View</p>
{{else}}
<p>Access Denied</p>
{{/if}}
{{#each contacts}}
<p>Name: {{fullName}}</p>
{{/each}}
{{#unless newUser}}
<p>Welcome back</p>
{{else}}
<p>Good to have you here</p>
{{/unless}}
Template Helper Functions
To interact with templates with javascript, Meteor converts all template sections into JavaScript functions that are accessible via a global Template namespace.
To provide data to templates, add functions on Template.template_name object.
Template.hello.name = function() {
return "Bharani" + "M";
}
Template.hello.name = "Bharani";
In Javascript file
In HTML file
<template name="hello">
<h1>Hello, {{ name }}</h1>
</template>
Template Events
To respond to user inputs, we need to listen for events like “click”, “double click”, keypress” etc.
The event and the target element is specified as a string value by a space. This forms the key of the object. The callback function that gets executed when this event occurs is defined as the value.
Template.hello.events({
“click input” : function(e, t) {
alert(“You clicked the input.”);
}
});
Reactivity
Reactive programming
Results will be automatically recalculated whenever data associated with that piece of code changes.
Reactive data sources - a data store that will update its templates when its value itself changes
-
Session Storage
-
Collections
-
Meteor.user
Reactive contexts - run code as a reactive computation
Session Storage
Global reactive store of data
one session - accessible everywhere on the client
Session storage allows us to store key-value pairs that are reactive in nature. This can be used to keep track of the current page or current user or for keeping our UI in sync.
Session.set("currentTask", "Learn Meteor");
Session.set("currentPage", "documentationPage");
Session.get("currentTask");
Session.get("currentPage");
Session.equals("currentTask", "Learn Meteor");
Collections + MongoDB
Persistent Data Storage
The client and server share the same database API. Meteor automatically synchronizes data between client and server
Every Meteor client includes an in-memory database cache. Server publishes sets of JSON documents and clients subscribes to those sets.
Meteor currently only supports MongoDB for persistent data storage
Collections
Contacts = new Meteor.Collection("contacts");
Collections are a way to talk to the Mongo database.
Collections allow us to publish and subscribe to certain sets of data and take care of synchronizing real-time data to and from each connected user's browser and the Mongo database .
Collections mimic Mongo's API closely.
Server Side Collections
On the server, Collections act as the interface for talking to Mongo database. Server side collections allow us to use Mongo commands -
Contacts.insert()
Contacts.update()
Contacts.find()
Contacts.remove()
Client Side Collections
On the client, Collections act as an in-browser cache of the actual Mongo database. It contains a subset of the actual data and provides immediate access to data.
No round-trip to server to get the data as it is pre-loaded on initial page load.
Minimongo
Working With Collections
Inserting Records
Contacts.insert({ name: "Bharani" });
Finding Records
Contacts.find();
Contacts.find({ name: "Bharani" });
Contacts.findOne({ name: "Bharani" });
Updating Records
Contacts.update({ name: "Bharani" }, { $set: { name: "John Doe" }});
Deleting Records
Contacts.remove({ name: "Bharani" });
MongoDB Crash Course
Document oriented database
Alternative to Relational Database (RDBMS) Systems
Mongo database can have multiple collections. Collections are similar to Tables.
Collections can have multiple documents. Documents can be thought of as 'rows'
Documents can have multiple fields. Fields are similar to columns.
Each document inside a collection can have unique set of fields. It is schema-less.
When we get data from Mongo, we get a cursor - actual execution only happens when necessary.
MongoDB Crash Course
Every document must have unique _id field. This field is indexed by default.
db.collection_name.find({ field1: value1, field2: value2 });
db.collection_name.find({ field1: { $gt: 100 }});
db.collection_name.find({ field1: { $lt: 100 }});
db.collection_name.find({ field1: { $exists: false }});
db.collection_name.find({ field1: value1, $or: [{field2: value2}] });
db.collection_name.find().sort({ name: 1 });
db.collection_name.find().count();
db.collection_name.count({ age: { $gt: 18 }});
db.collection_name.find({}, { age: 1, _id: 0 });
MongoDB Crash Course
db.collection_name.update({ title: "Post #1"}, { $set: { votes: 0 } })
db.collection_name.update({ title: "Post #1"}, { $inc: { votes: 1 } })
db.collection_name.update({ title: "Post #1"}, { $push: { tags: "first_post" } })
db.collection_name.remove( { type : "food" } )
db.collection_name.remove( { type : "food" }, 1 )
MapReduce, Geospatial, Denormalization, Two Phase Commits
Application Structure
You can write an entire app in just one file.
Meteor provides you an efficient way to structure and organize your files. There are no script tags, no loader libraries and no dependency management.
Just put files in appropriate folders and Meteor will pick it up automatically.
Application Structure
-
/client - For code that only runs on the client. Meteor pre-processes files in this folder and minifies it before rendering. Place for putting CSS/SCSS/Less files.
-
/server - For code that only runs on the server. Keep your API keys and other private data files in this folder so that it is not accessible by users. (You can also use /private for this)
- /public - Place to store images, robots.txt etc. (CSS files are not considered static assets)
Accounts
Meteor provides a pre-built user authentication module. It includes support for 3rd party authentication services (oauth)
accounts-base, accounts-password, accounts-facebook, accounts-github, accounts-google, accounts-meetup, accounts-twitter, or accounts-weibo
Also include a UI that provides login/signup forms
Accounts
meteor add accounts-base accounts-password accounts-ui
{{loginButtons}}
<template name="header">
{{loginButtons}}
</template>
{{#if currentUser }}
<h1>Logged in</h1>
{{/if}}
Meteor.user()
Meteor.userId()
Security
Restricting Read Access
Publications and Subscriptions
Restricting Write Access
Allow/Deny
Meteor Methods
Restricting Read Access -
Publish/Subscribe
Meteor includes autopublish package by default which automatically mirrors all data from the server on the client.
meteor remove autopublish
Client should only get a subset of data. To restrict data access, we create a publication channel. Publication is a way to transfer data from server to client.
Then client then connects (subscribes) to that channel.
Publications control what data should be passed from server.
Publish/Subscribe
From server
From Client
Meteor.autosubscribe(function() {
Meteor.subscribe("contacts", Meteor.userId());
})
Meteor.publish("contacts", function() {
return Contacts.find({ userId: this.userId });
})
Restricting Write Access -
Allow/Deny
Permission system that applies to all database changes initiated from the client. Declarative way to specify what database modifications are allowed
Contacts.allow({
insert: function(userId, doc) {
return !!userId
},
update: function(userId, doc) {
if(userId && doc.userId == userId) return true;
return false;
},
remove: function(userId, doc) {
if(userId && doc.userId == userId) return true;
return false;
}
});
Restricting Write Access -
Meteor Methods
Meteor.call("addOne", {name: "bharani"});
Methods are functions that are called from the client but are executed on the server.
From Server
From Client
Meteor.methods({
addOne: function(obj) {
Items.insert(obj);
}
})
Deploying
meter deploy contacts-app-demo.meteor.com
meteor bundle contacts.tgz
tar -zxvf bundle.tgz
Meteorite
Meteorite is a Meteor version manager and package manager. It provides an easy way to run different versions of meteor, use non-core packages, and to install packages from the Atmosphere package repository .
npm install -g meteorite
mrt create my_app
mrt add ... (add a package from Atmosphere repository)
Useful Meteorite Packages
-
Router
-
User Roles
-
Admin UI
-
Pagination
-
Animate
-
SCSS
-
Bootstrap 3 / Zurb Foundation
-
Regulate/jQuery Form Validations
-
Momentjs
Learning Resources
Documentation
Meteor Youtube Channel
Code examples
Video Tutorials