For a long time, I’ve been working with Node.js and Express on the server side, and jQuery and other popular JavaScript frameworks for front-end development. Some time ago I started working for a company that is using Meteor for around 80% of all their projects. After I got to learn and work with Meteor for some time, I feel it is a step in the wrong direction. Before you get out your pitchforks and torches, let me explain why.
The Good
Isomorphic and universal apps
Sharing client-side code with back-end code is probably the holy grail right now. Having the same code running in the browser and on the server is very convenient. We get to share some of the JavaScript files that are often called “business logic”: be it controllers, models, validation or even constants. This saves us time and effort re-implementing the same front-end logic on the back-end.
Minimongo
Minimongo is simply amazing. Having a full MongoDB-like interface in the browser which behaves like a full MongoDB database. We get to inspect the whole database in the browser just by opening up the browser’s developer console. In debug mode even, it automatically synchronizes with our back-end database when we change a value. To some degree it feels very similar to PouchDB, a CouchDB-inspired database. When comparing PouchDB directly to Minimongo, I feel Minimongo has the upper hand, mostly because querying for data requires less effort.
The Bad
Package Management
Meteor comes with its own package management system called Atmosphere. The problem is most of the packages that include popular libraries are not being maintained by its original authors on Atmosphere. This leads to you not knowing what the package actually includes and if it’s being updated as regularly as the original module. Some packages may even include more than the official distribution, and some less.
Module Management
The notion of modules does not exist in Meteor at all. Meteor loads all the files in their alphabetical order as they are present in the file system. I’ve seen projects where this resulted in interesting prefixes for the file names, such as underscores, double underscores or numerical identifiers, or a combination of those.
You are essentially working with global variables on the server and client side. As a result, you pretty much have to deal with everything you had to deal with before modules (like CommonJS, AMD or ES2015) became popular and the de-facto standard.
As you don’t have control of when your client-side scripts will be loaded, you need to rely on checking for your own scripts and third-party libraries in the global scope. This is my most prominent and major gripe with Meteor. Meteor gives us a default load order for our libraries, but there are some instances where we need to change that, for example when we have multiple libraries depending on each other. With popular module options, we need to define our imports and exports explicitly, but this adds predictability to modules and we know which modules interact with each other. In Meteor, we don’t have that and this may lead to side effects if we are not careful enough.
The Ugly
Enforcing bad practices
For a variable to be available on both the server and the client, we omit the var
keyword when defining that variable. While Meteor bundles the JavaScript files for us, it wraps function around our JavaScript code and inserts the var
statement for us. This will be safe in the end result, but it still feels as taking advantage of one of JavaScript’s pitfalls.
Compatibility with Node libraries
Meteor uses a library called Fibers for control flow. Pretty much all asynchronous actions in Meteor feel synchronous and are being defined that way. Usually callbacks, promises, generators and async/await are the prominent solution to deal with asynchronicity. Asynchronicity is a core concept in JavaScript, and one I’ve seen many developers struggle with. Since there is a huge gap between how libraries in Node.js and Meteor handle control flow, compatibility is not always given. While Meteor can work with most NPM libraries, it becomes difficult the other way around.
Atmosphere is closed source
Atmosphere is not open sourced. While this in itself may not necessarily be an issue, I can’t help but wonder what would happen if the company behind Meteor wouldn’t exist any more. Who will take over Atmosphere, provide maintenance and cover the costs?
Wrap up
There are some minor gripes I have with Meteor, for example there are some instances where I feel its documentation is not as thorough as I would like it to be, or a few things can be misinterpreted — especially for those just starting out in the JavaScript world.
All in all, I feel Meteor got stuck with its original design decisions, and its development since hasn’t been as radical as it should have been. As much as we crucify the Angular 1.x to 2.x version changes and its more-or-less complete redesign, I feel something like that might actually help Meteor. While Meteor is embracing ES2015 with its newest release, I would like to see more of these concepts brought over to Meteor: Using the ES2015 module system, ES2016’s async/await syntax for control flow, class decorators and a better notion of UI components are some of the ideas I would have in mind.
Would I have a different opinion if Meteor was an Express middleware and I would be able to specify and control certain aspects. For example, specify how and which files get loaded, instead of it being abstracted away into a seemingly “black box”. Definitely.