The Old, Old Way
A couple years ago I moved to a large company with an extremely large codebase and eventually needed to work on some big enhancements to one of their web based subsystems. I dug into the code to attempt to figure out what I needed to do to get the job done. I found a huge, un-maintainable mess which was the result of people coming and going and just tacking on bits here and there, then forgetting about it. There was no way I was about to get in there and do the same thing. At this point, I had never used an MV* framework in the browser but I knew that they were probably the answer I was looking for. I started researching and eventually decided on Angular.
While I was researching the different frameworks I did stumble upon meteor but I think it was just getting started and no was nowhere near usable for this project - although I was very intrigued by it’s core principles. The project I was working on, already had an extremely large backend with a SQL database, and there was no way I could do anything about that, so using a full stack framework like meteor was out of the question anyway.
Apps Need Templates, Templates Need Data
One of the first things we had to do for this project was restructure how data was accessed. This involved writing a new REST API on the server side that our Angular app would use. We were then able to implement Angular’s resource service to abstract away access to our API, which worked great for us. In contrast, Meteor uses a publish/subscribe architecture. On the server you define publications of data that are based on a query you provide. On the client, you subscribe to those publications when you need to use the data. The result set of your publication is streamed to the client via websockets, stored in the browser’s memory and then is made accessible to your application. Updates made to this data on one client are pushed back to the server and subsequently, published back to all connected clients! This takes the pain out of orchestrating how changes to the data are reflected between users.
Both frameworks have the concept of what meteor calls “reactive data sources.” In Angular, you have the scope object. The scope object creates a hierarchy, where you can assign values and functions. You can then access these values from your templates. Your views will automatically be updated when values on the scope change, giving your application a single point of truth in its model. Angular also allows you to watch and observe these data sources and take custom actions when the value changes. Meteor includes several reactive data sources out of the box. The simplest example is the session. The session object allows you to reactively store arbitrary key-value pairs in the browser’s memory. Cursors are another important reactive data source in Meteor. A cursor is what is returned when you query the database. The combination of reactive data sources and the pub/sub pattern are what make meteor so magical! When changes occur to your data on one client, those changes are reflected in your views immediately and also sent to the server, which then streams the changes back down to all other connected clients! Cursors also allow you to tap in and directly observe when changes occur to your data.
One of the standout features of Angular is it’s concept of directives. Directives allow you to define custom HTML tags that represent isolated components to be declaratively laid out in your HTML templates. Directives usually include their own template to be injected or transcluded into. This is where you wire up events and behaviors on the DOM. You can then reuse these widgets anywhere in your app. Meteor achieves this behavior currently using normal templates, which under the hood are called “components.” The API for creating custom components is a bit hidden and undocumented, but I’m looking forward to seeing how they evolve - hopefully into something as powerful as Angular directives.
An important part of using a new framework is the supporting tools. Meteor isn’t just a framework, it also includes a nice command line tool. Starting your app is extremely easy. Just run ‘meteor run’ in your project directory and it starts up a web server and automatically watches your files for changes and automatically refreshes your browser for you. It’s also extremely easy to add support for CoffeeScript, LESS, or anything else you might need. The tooling takes care of source-mapping, concatenation, and minification right out of the box, letting you focus on the application. To get similar functionality in an Angular project, you’ll need to spend at least some time messing with Grunt to get things perfect. There are, however, some great Angular boilerplate apps that have a lot of this done for you.
Angular does have a bit of a learning curve but makes great usage of some more advanced programming patterns, which can seem daunting at first. On the other hand, Meteor is extremely easy to pick up and run with. You can get a lot done with a relatively small amount of code and can work your way up to using the more advanced features as you learn.
After working with Meteor full-time for the past 7 months, it’s hard for me to imagine many situations where Meteor wouldn’t be my first choice. It has changed the way I think about writing apps and I can’t imagine going back. Meteor is still pre v1.0 and things are always improving. Looking at the Meteor Roadmap Trello board, it is clear that the few shortcomings I have mentioned should be addressed by the time v1.0 lands or soon after. Meteor is just getting started and I can’t wait to see where things go from here.