client
and public
subdirectories, and loads them into a Node.js
server instance inside a fiber. In Meteor, your server code runs in
a single thread per request, not in the asynchronous callback style
typical of Node. We find the linear execution model a better fit for
the typical server code in a Meteor application.
There are more assets to consider on the client side. Meteor
gathers all JavaScript files in your tree with the exception of
the server
and public
subdirectories for the
client. It minifies this bundle and serves it to each new client.
You're free to use a single JS file for your entire application, or
create a nested tree of separate files, or anything in between.
Files outside the client
and server
subdirectories are loaded on both the client and the server! That's
the place for model definitions and other functions. Also, instead of
putting client and server functions in different directories, you can
use the is\_client
and is\_server
variables to isolate JS to one or the
other side.
CSS files work just the same: the client will get a bundle with all
the CSS in your tree (excluding the server
and public
subdirectories).
In development mode, JS and CSS files are sent individually to make
debugging easier.
HTML files in a Meteor application are treated quite a bit
differently from a server-side framework. Meteor scans all the HTML
files in your directory for three top-level
elements: <head>
, <body>
,
and <template>
. The head and body sections are
seperately concatenated into a single head and body, which are
transmitted to the client on initial page load.
Template sections, on the other hand, are converted into JavaScript
functions, available under the Template
namespace. It's
a really convenient way to ship HTML templates to the client.
See the templates section for more.
Lastly, the Meteor server will serve any files under
the public
directory, just like in a Rails or Django
project. This is the place for images, favicon, robots.txt, and
anything else.
{{/markdown}}
// server: publish all room documents, and per-room messages Meteor.publish("chatrooms"); Meteor.publish("messages", { selector: function (room_id) { return {room: room_id}; } });
// client: subscribe to all rooms, and messages in the first room Meteor.subscribe("chatrooms"); Meteor.subscribe("messages", Chatrooms.find()[0]._id);Document modifications also propagate automatically. To insert, update, or remove a document, client code uses the familiar MongoDB API. That change instruction is executed immediately on the client's cached data. At the same time, the client sends that instruction up to the server, which executes the same change against the master database. Usually the client and server agree, but should they differ (permissions checking or overlapping with another client, for example), the server's result will publish back down to the client. And of course, all other clients with a matching subscription automatically receive an updated document.
// create new message, executes on both client and server. Messages.insert({room: 2413, text: "hello!"});Putting it all together, these techniques accomplish latency compensation. Clients hold a fresh copy of the data they need, and never need to wait for a roundtrip to the server. And when clients modify data, those modifications can run locally without waiting for the confirmation from the server, while still giving the server final say over the requested change. {{/markdown}}
Meteor.autosubscribe(function () { Meteor.subscribe("messages", Session.get("current_room")); });In this example, the client sets up a subscription for the messages in the client's current chat room.
Meteor.autosubscribe
runs the
function it is passed in a reactive context, meaning it will notice when
the current room changes (Session.get("current_room")
) and
automatically rerun the function to compute the new subscriptions. In a
non-reactive program, the caller would have had to manually reset the
subscription whenever the selected room changed.
These Meteor functions run your code in a reactive context:
* Meteor.ui.render and Meteor.ui.renderList
* Meteor.autosubscribe
* Templates
And the reactive data sources that can trigger changes are:
* Session variables
* Database queries on Collections
* Meteor.status
Meteor's implementation
of reactivity is short and sweet, about 50 lines of code. You can
hook into it yourself to add new reactive contexts or data sources,
using the Meteor.deps module.
{{/markdown}}
Meteor.ui.render
and Meteor.ui.renderList
. Templates
provide a way to simplify the process even further, allowing you to
write your HTML structure directly in HTML files.
To create a template, include a <template>
tag with
a name attribute in any HTML file, whose content is the template text.
The template will be compiled and made available as a function on
the Template
object. The function takes some JSON data
as input, and returns a DocumentFragment
. Insert the
DocumentFragment
anywhere you like — it will
automatically update itself as the data it depends on changes.
<!-- in myapp.html --> <template name="hello"> <div class="greeting">Hello there, {{first}} {{last}}!</div> </template> // in the JavaScript console > Template.hello({first: "Alyssa", last: "Hacker"}); => <div class="greeting">Hello there, Alyssa Hacker!</div>In addition to passing JSON data directly to the template function, you can also provide data to templates by setting additional properties on the template function. You can pass in functions this way, and use them just like you would use data that was passed in as JSON.
Template.players.top_10_scorers = function () { return Users.find({}, {sort: {score: -1}, limit: 10}); }; <!-- Use it like this --> <template name="players"> {{#each top_10_scorers}} <div>{{name}}</div> {{/each}} </template>Functions can take arguments, and they receive the current template data in
this
.
Template.players.league_is = function (league) { return this.league === league; }; <!-- Use it like this --> <template name="players"> {{#each top_10_scorers}} {{#if league_is "junior"}} <div>Junior: {{name}}</div> {{/if}} {{#if league_is "senior"}} <div>Senior: {{name}}</div> {{/if}} {{/each}} </template>
{{#if league_is "junior"}}
is
allowed because of a Meteor extension that allows nested helper
calls. (Both if
and league_is
are
technically helpers, and stock Handlebars only allows one helper
invocation per expression.)
// Works fine with {{#each sections}} Template.report.sections = ["Situation", "Complication", "Resolution"];Finally, you can set the
events
property of a template
function to a table of event handlers. The format is documented at
event map. The this
argument to
the event handler will be the template data.
<!-- myapp.html --> <template name="scores"> {{#each player}} {{> player_score}} {{/each}} </template> <template name="player_score"> <div>{{name}}: {{score}} <span class="give_points">Give points</span> </div> </template> <!-- myapp.js --> Template.player_score.events = { 'click .give_points': function () { Users.update({_id: this._id}, {$inc: {score: 2}}); } };Templates are reactive — they are automatically wrapped in
Meteor.ui.render
. So, the DOM
elements they return automatically update themselves.
<!-- in myapp.html --> <template name="forecast"> <div>It'll be {{prediction}} tonight</div> </template> <!-- in myapp.js --> // JavaScript: reactive helper function Template.forecast.prediction = function () { return Session.get("weather"); }; <!-- in the console --> > Session.set("weather", "cloudy"); > var x = Template.forecast(); => <div>It'll be cloudy tonight</div> > document.body.appendChild(x); > Session.set("weather", "cool and dry"); > x => <div>It'll be cool and dry tonight</div>The auto-updating continues as long as the elements are on the screen. The specific rule is: if the elements are not children of
document
when
Meteor.flush
runs, then Meteor may
stop updating them so that the browser's garbage collector can clean
them up.
{{/markdown}}
.coffee
files in
your tree. Once added, you can write your application in CoffeeScript
instead of JavaScript.
* The jQuery
and Backbone packages are examples of using
Meteor to prepackage client JavaScript libraries. You could get
the same result by copying the JavaScript files into your tree, but
it's faster to add a package.
* The underscore package extends both the
client and server environments. Many of the core Meteor features,
including Minimongo, the Session object, and reactive Handlebars
templates, are implemented as internal packages automatically
included with every Meteor application.
You can see a list of available packages
with meteor list,
add packages to your project
with meteor add, and remove them
with meteor remove.
See the Package List section for a description
of the existing packages.
$ meteor deploy myapp.meteor.comYour application is now available at myapp.meteor.com. If this is the first time deploying to this hostname, Meteor creates a fresh empty database for your application. If you want to deploy an update, Meteor will preserve the existing data and just refresh the code. You can also deploy to your own domain. Just set up the hostname you want to use as a CNAME to
origin.meteor.com
,
then deploy to that name.
$ meteor deploy www.myapp.comWe provide this as a free service so you can try Meteor. It is also helpful for quickly putting up internal betas, demos, and so on. ### Running on your own infrastructure You can run also your application on your own infrastructure, or any other hosting provider like Heroku. To get started, run
$ meteor bundle myapp.tgzThis command will generate a fully-contained Node.js application in the form of a tarball. To run this application, you need to provide Node.js 0.6 and a MongoDB server. You can then run the application by invoking node, specifying the HTTP port for the application to listen on, and the MongoDB endpoint. If you don't already have a MongoDB server, we can recommend our friends at [MongoHQ](http://mongohq.com).
$ PORT=3000 MONGO_URL=mongodb://localhost:27017/myapp node bundle/main.js
npm
available, and run the following:
$ cd bundle/server
$ rm -r fibers
$ npm install fibers@0.6.3