An overview of MeteorJS
As I have mentioned earlier, MeteorJS is an open source isomorphic framework that is built using JavaScript that runs on Node.js. The beauty of the framework lies in the core principles of the framework. A truly modern application needs to be highly reactive. To be reactive, the existing stack is not that great. HTTP is slow because of the latency in handshaking on every request. The databases that we use are not reactive. HTML needs to be updated as and when the data changes, which is an overhead for developers. Also, the updated data must be transferred to all the clients without a refresh or manual intervention. MeteorJS provides a one-stop solution for all these problems and needs.
To master something, it is not enough to know how to use it, but also it is absolutely necessary to know the internal working of the thing. In our case, it is really important to know the working principles of MeteorJS to master it.
MeteorJS is built using a bunch of packages that can be used independently in one of your projects if needed. Let's take a deeper look into these packages.
A typical MeteorJS application has three parts: the server, the communication channel, and the client. Once a server is connected to a client, there is a socket introduced between the client and the server. Any data transfer that happens between the server and the client is through this socket.
Server
The server is where MeteorJS is installed on top of Node.js. MeteorJS, on the server, is connected to MongoDB that is the default database for the framework.
MongoDB
MongoDB is a NoSQL database. Each record is a document and the set of documents is called a collection that is equivalent to a table in a SQL database. As you may know, MongoDB is an in-memory JSON-based database, which means it is extremely fast in favorable conditions. Usually, MongoDB can have operation logs, which is called oplog. The oplog has the database operations happening with time. This is used in the case of making the replica (slave) of the primary database. The operations that happen in the primary database are copied to the secondary databases asynchronously.
Though MongoDB is not a reactive database, Livequery, which is a part of MeteorJS, does some work internally to get the updates of the database periodically. Livequery can connect to the database and set triggers on certain conditions as required. In the case of MongoDB, triggers are not supported. So, the Livequery depends on oplog if enabled, or else it will poll the database at a particular interval. When oplog is enabled, which should be the case for production, MeteorJS observes the oplog and intelligently does the transaction. If oplog is not enabled, meteor polls the database, computes the diff, and then sends the changed data to a client. Livequery can guess when to poll the database as all the write operation to the database go via Livequery.
Publish/Subscribe
A very important part of MeteorJS is this good old design pattern. By default, the entire Mongo database is published to the client from the server. However, it is not good for production to auto-publish all the data to the client. Instead, the client can subscribe to the required data that is published by the server. The subscriber will automatically be updated whenever there is a change in the subscribed data:
/* Publishing from server. */ if (Meteor.isServer) { Meteor.publish("tasks", function () { //Registering "tasks" publication return Tasks.find(); }); } /* Subscribing from client */ Meteor.subscribe("tasks");
Communication channel
In the realm of publish and subscribe, there should be a way to transfer the subscribed data. MeteorJS uses a protocol called Distributed Data Protocol (DDP). To define DDP, it is simply a REST over Web socket. It is a socket implementation that can transfer JSON data to and fro (duplex). MeteorJS uses Socket.io internally to establish a socket connection between the client and the server. However, neither the client nor the server knows to whom they are talking to. All they know is to talk DDP over the socket.
DDP is human-readable and one can literally see what is transferred via DDP using the package Meteor DDP analyzer. Over DDP, there will be either a message transfer or procedure calls. You can use DDP not only with MeteorJS, but also with any other languages or projects that can support socket. It is a common standard protocol that gives a great way to pair with any other DDP-consuming implementation, if required. Sockets reduce latency in a very high rate than HTTP, because of which it is very much suitable for reactive applications.
Client
Let's say the server is ready with the data. How does the client keep all this data so that it can be reactive? Also, who is doing the magic of refreshing the views when the data changes?
Modern apps try their best to solve two things as intelligently as possible. One is latency compensation and another is reactivity. MeteorJS does that quiet powerfully using the following implementations.
MiniMongo
Being a developer, if you are implementing a table that can be sorted, filtered, and paginated, what will you do to make it faster? Won't you fetch the data and keep it in browser memory in the form of multi-dimensional array, apply all the operations on the cached array, and update the table as and when required? The same is the case for MeteorJS with little advancement in the cache implementation. Instead of using a plain object or array, MeteorJS creates a cache in the browser called MiniMongo, which is again a simplified client memory database. The highlight is that you can query it in the way you query the MongoDB that enables you to use the same query both in the client and the server.
Whenever there is change in MongoDB, the server sends the difference to the client and that data is stored in MiniMongo. At any instance, MeteorJS tries to keep both the MongoDB in sync.
Tracker
Now, the data is with the client. Let's call this model. In a MV* framework, we have the views bound to models to auto-update the views as the model changes. In Backbone.js, you have to do it explicitly. However, in Angular.js, it is taken care of by the framework itself with the help of $
scope and digest cycles. How does MeteorJS handle data changes? With the help of Trackers. Trackers create observers for everything you need to track. By default, MeteorJS has enabled a tracker on certain data sources, such as database cursors and session variables. You can even have a custom variable to be tracked using the tracker.
Blaze
Blaze is a templating engine that is reactive because of the tracker. Blaze plays the magical part of reactivity by binding the data to the templates. An important point to note is that Blaze is declarative, which means you just have to tell Blaze what to do when the data changes, and need not say how to do it. With the help of the tracker, Blaze keeps a track of model changes and reacts to the change. The default templates are spacebars. This is a variant of Handlebar's templating engine. You can use Jade as well. Blaze is again intelligent to compute the diff of what needs to be updated. It doesn't update all the template until it is necessary. Blaze handles the user interactions and thereby makes a call to the server, if absolutely needed.
Additional information
Developers can use MeteorJS ecosystem, which has a lot of packages to use in the application. Iron router, masonry, auto-form, simple schema, and twitter bootstrap are a few important packages for application development. Being a Node.js-based framework, developers can harness the power of Node.js ecosystem as well. You can also use NPM packages in the MeteorJS application.
MeteorJS does hot code deployment, which means without restarting the application, the code is deployed and the client will see the changes without completely refreshing the browser.
Note
MeteorJS has just reached 1.x. There are many new features and implementations yet to come such as drivers for different databases, support of various front-end frameworks, and so on. However, basically, MeteorJS is designed in a way to accommodate anything just by small integration work. If you really want to see if this is true, check their source in GitHub (https://github.com/meteor/meteor/tree/devel).
It was said, "To know the truth, return to the source".
If you are interested in learning more about the framework's internals, I would suggest take a look at the source code that will help you learn a lot of new things.