I left Meteor
And you can to.
Anyone who follows me on Quora knows I’ve been backing Meteor.JS hard for a couple of years now. Of course while doing so, the new “pretties” showed up. So first a timeline:
Let’s go all the way back.
- 2009 — Mustache, and later Handlebars provide client side templating to jQuery. When set up right, with a library like backbone, it became really feasible to write single page applications.
- 2012 — Meteor.JS is released. It mixes the best of Knockout with Handlebars while adding for the first time, full stack reactivity.
- 2012 — React.JS comes out. It is the first library on the web to introduce the component architecture.
React and Meteor coexisted separately for many years. Fast forward 2 years from this point and we get to 2014, when I started caring about either of them. Angular 1 existed, but it held a niche really reserved for the MEAN stack. Meanwhile, Meteor with it’s mongodb backed full stack reactivity held a lot of potential. At the time, getting a fully reactive SPA was complicated. It could be done, there were tools that could do it, if you took the time to bolt them together. But with Meteor you didn’t have to. It just worked. Built in file watch rebuilds and hot refresh meant that I could see the results of my changes very very quickly.
That wasn’t so bad though. The convenience of Meteor kept me comfortable with being a few months behind the curve feature wise. I mean, the ridiculous pace wouldn’t continue forever right? Well, around the same time, Meteor deprecated it’s view layer suggesting that instead React (or Angular, if you wanted to try to support it) would be the ideal view system. So I started using React. The first thing I noticed was that while I couldn’t easily rip out Blaze, I could easily load react components into blaze templates. The other way around was far more complicated sadly. Also, SSR was still not a thing in Meteor, despite the fact that all experts suggested that it was kind of critical to performance.
Slowly but surely, everything that was Meteor in my stack was getting replaced. When Meteor announced they were going to be working on GraphQL implementation, I got excited again. That is, until I used it. I loved the GraphQL implementation, but I had to fight with Meteor the whole way. And then, I thought “I’ll rip out mongo since i’m not using it anymore.” Nope. It turns out that even if you rip mongo out of the application entirely, there is a chance of it still getting included by another package which depends on it. And almost every package does. So I couldn’t actually build an app in Meteor without including mongo, and I don’t really need mongo. This started me down the path to replacing everything that Meteor was and is.
The logical alternative
I was in dire need of a logical alternative. I found that alternative in webpack. I set out on a solution finding mission, and here were my goals:
- Allow me to write my code using entirely ES6 modules or typescript
- Allow me flexibility to use whatever babel plugins I saw fit.
- Hot reloading server capable of patching itself while running.
- Maintain the environment mapping Meteor had including knowing whether my code is currently executing on the server/client and wrapped “universal” replacements for several key functions, most specifically timers and ajax/http.
- Allow me to add random files and have them suddenly be part of the app bundle, without changing anything.
- Allow me to not have that behavior if a folder in the file’s path includes the word “imports” (a behavior Meteor has)
- Allow me to import files for both server and client, but put them in folders named “server” or “client” and have webpack prune the “wrong” one.
- Full SSR with Metadata
- SSR has optimal render path mapping, loading only what CSS is absolutely critical in order to draw “above the fold” content, or even just a loading widget. Remaining content loads after render, except in a case of noscript (some bots) in which case it loads before, delaying the render slightly.
I accomplished all of those goals. I have an SSR application which, complete with multiple API requests, typically gets 500ms or less time to first paint. First paint includes navbar/header and a loading indicator. On a typical 3g connection with an older model phone (I use the iPhone 5 as my “minimum” target) I have first paint in 1.3 seconds reliably.
My application stack uses the following key technologies:
- GraphQL using Apollo on both client and server.
- and of course Webpack2
Over the next few months, I will be writing a series of articles outlining how I accomplished each of these goals. I want to be clear that my solution is drop in using Node.JS. Nowhere did I modify any core libraries. All of the work I did to set this up was mostly in research to understand how webpack worked. Now that it’s done, I have a really great baseline for applications, and in one week, replaced everything that Meteor was to me. That said, I love the work that the Meteor devs have done on Apollo.
Keep an eye out for future posts as I share how I accomplished this.