Meteor is Awesome. Next is Awesome. I love both frameworks, but they cannot be compared. It’s not even apples compared to oranges. One is an apple and the other is a basket full of apples. The risk of this basket is that there is always this rotten apple that you might want to throw away even though you’ve now paid for it. The real question you should ask is does the price of buying the apples separately outweigh the price of buying 1 basket and throwing away some of them. Even more so, if you consider that the apples of the basket were picked by real apple experts, do you really want to take the risk of picking the wrong apples yourself?
Both Next and Meteor have their purpose and what you should look at is what they give you vs what you have to build or throw away.
Where Next.js shines
Next.js is your apple. It’s an amazing view layer and it provides you with all the tooling needed to easily integrate your React frontend. Not only that, it follows some nice patterns to allow plug-ability which keeps your code-base nice and tidy. Some of the things where Next.js really shines is pre-rendering, serverside rendering + hydration, routing and optimized hot module replacement capabilities. In other words, it takes care of all the complex render related stuff and provides convenient functionalities to hydrate your components using getServerSideProps and getStaticProps and also a nice CLI tool to help you build and pre-render it for serverless purposes.
What Next.js lacks
One HUGE thing that Next.js doesn’t have though a solid thought trough state layer with best practices in how to use it. With state layer I mean both UI state and domain state. Luckily Next.js is React which means that you can be assured of powerful UI state capabilities using React hooks and the context API.
UI State is not domain state
It should be clear that there is a huge difference between the UI state and domain state. Even more so, the way you manage domain state is totally different than UI state. There's an article with an excellent explanation about the difference between the two.
In short: UI state is essentially the internal state of your components and layout. For example a dropdown that is open or a collapsed menu. View state is unique to an app. Domain state however is business related and is unique to a business. For example in a webshop domain state would be the products and product categories, for a blog this would be articles and the categories of those articles. The real downside of Next.js is on the domain state side, because there is none, except for the hydration helpers that I’ve just mentioned.
Of course you could use a tool like ApolloJS, but that means that you need to create another API application for its server and you need to install its client into the next project, provide it with all the boilerplate and create mechanisms to provide serverside rendering.
I’ve seen most developers do Apollo Integrations or in fact any API integration VERY wrong, creating a fundamentally broken project that requires months of refactoring to get it in good shape. Its exactly this practice that developers in companies never get time for.
React's history of breaking changes
Next.js is React. I’m very experienced in React, but I need to admit that React is a moving target. I would consider it a low level UI component abstraction with powerful state management tools like hooks and providers, but besides basic documentation for its tools, it does not promote many best practices with the result of having a very scattered community. That React is a low level API also reflects back on the number of breaking changes. React is at time of writing on version 17/18. Any project (that includes the Next based ones) that has been there for a couple of versions has had to go trough quite some refactor rounds just keep everything up to date.
Where Meteor shines
Meteor is your basket of apples. It has mostly awesome stuff. Especially on the server. The server by default is typically THE frontender’s weekpoint. Since the introduction of so called BFF’s (Backend for frontends) - which promised to provide a proper abstraction over existing frontends I’ve seen people doing Express.js integrations that make me cringe. Even worse, without them knowing it, they are essentially reinventing something that Meteor OWNS to the core from when it first appeared 8 years ago (2012).
The Unfortunate Meteor Paradox
It’s a paradox. People were shooting at Meteor, because it “was hard to make it work with existing backends”, but now we are introducing “BFF’s” that should provide the exact level of abstraction that Meteor gives us, but most devs fail to build an efficient toolkit that even closely matches that of Meteor. Even worse, I found myself diving into existing projects of just 2 years old and it unfortunately had to become my sole purpose to maintain parts of the API that I would never even have to touch in Meteor.
Microservices - The biggest argument against Meteor
As some of you might know. Meteor has and still markets itself as a full-stack platform. This is the official guide catch-phrase: "Meteor is a full-stack JavaScript platform for developing modern web and mobile applications.".
Somehow developers can't see the difference between a micro-service architecture and the term full-stack. Because of that they wrongly put Meteor into a corner of "not working as part of a large ecosystem". Did you know that micro-services themselves are "stacks"? Just look at ANY application that runs with SSR enabled. There is a server involved. Even more so, bigger sites often introduce the concept of BFF's to act as an API purely designed for 1 specific frontend. Meteor IS the ideal BFF AND your frontend. But what about Mongo and Minimongo? You don't 'have' to use it, but even for this there are some good reasons to do so - even if you don't have a Mongo database.
Minimongo is a undervalued domain state library
Meteor works with, but also without Mongo. Most people dont realize this, but is very easy to NOT use Mongo, but still Minimongo. Minimongo is the number 1 type of library that I always miss when building big UI interfaces. I get optimistic UI and server sync for free. In Apollo this is still very complex. Unfortunately Minimongo has been originally built to work closely with Mongo (hence the name) and that’s why people get confused by it. Best way to look at Minimongo is by looking at it as a full-stack domain data layer for the UI with powerful query and sync mechanisms. It’s NOT Mongo, but it does use similar powerful features. You can use ANY backend as has been proven by the Redis Oplog package and the SQL integration layer. I’ve been using Meteor mostly on top of existing Rest backends. Here's the guide which illustrates how easy it is:
https://guide.meteor.com/data-loading.html#loading-from-rest
Meteor VS Apollo
So what about Apollo Server then? Well… GraphQL is awesome. Complex, but awesome. It’s complex, because it has a high learning curve. It forces standards and introduces a different paradigm, but I do feel that it’s the way to go. Meteor’s EJSON actually provides similar capabilities and together with Meteor's DDP Protocol and Minimongo it provides all the tools you need. You could also use DDP without Minimongo and have your own UI state manager.
EJSON + Minimongo is likely what has inspired the MDG folks to build a tool like ApolloJS. MDG is the company that initially built Meteor and later sort-of left Meteor to its faith and continued with ApolloJS. Tiny has acquired Meteor and seems to be igniting a spark in many idle Meteor developers. One thing that Apollo doesn't really have though is a high level API. It leaves integration of different tools to the developers and frameworks - which is good, but the same thing applies as what you see in the React community. Scattered practices and a lot of people creating API implementations that make me cringe.
If you do like Apollo (Like me) then you might want to look at using Apollo with Meteor. This way you leverage Meteor's and Apollo's advantages
Meteor integrates well with Blaze, React, Vue, Angular and Svelte
Meteor has a couple of “first class UI citizens” like Blaze, React and Svelte (Not tried Svelte, but it’s a cool new UI lib). It also provides Vue integration - though 3th party - but it illustrates that integrations are doable, though admitted not that simple for un-experienced people - especially doing the HMR part is difficult, but in all fairness, try to nail that with Webpack for the server side..
Another huge advantage of Meteor is its backwards compatibility and history of baby bottom smooth transitions to major version upgrades. That’s in contrast with Next. Given that Next works on top of React, I must say that the Next team does a good job of simplifying the transitions though.
Meteor's downsides
IMHO. Meteor’s biggest downside used to be its greatest asset, which is its built system. I love Meteor’s build-system, its very efficient in bundling for targeted clients. Old browser? Here’s a special bundle for you! Again I challenge you to try and configure such a feature with Webpack! The problem however is that most of the community has shifted towards Webpack, because of its plug-ability (Like WHY?! I just want my darn frontend to load magically, because build tools are boring… ain't nobody got time for that? No offence brilliant gods that maintain these things! I truly need and endorse you!). Somehow developers love doing these things themselves, because they think they are doing something really special - It’s horrifying. However a new trend is emerging. Vite is an emerging tool that relies on just the basic stuff. It’s VERY fast and simple to setup. Meteor might benefit from this new trend - though there are many directions and options on how to benefit from it.
SSR and hydration
Another downside is SSR and hydration for Minimongo. However you could of course just integrate Apollo Server and Client with Meteor and have the best of both worlds: https://www.apollographql.com/docs/react/integrations/meteor/ 1
In conclusion
Admitted. Both frameworks are awesome, but they work on different levels. Next.js, Nuxt.js, Gridsome and many other UI frameworks focus on JUST the render layer. They are the shiny apples. They have excellent documentations and I love the communities (big mention to the Vue and Nuxt communities and of course @evanyou - once part of MDG - and @akryum who has given us the Vue integration package for Meteor). Meteor is still a league of its own, because it's much more than 1 apple. It works with other tools like Apollo and the different UI libraries. You could even use Meteor’s server and integrate it with Next.js or Nuxt.js! In that case a package like SimpleDDP might be helpful to easily connect Next to Meteor's DDP API Many devs do this.
There are only a few frameworks that sort-of approach parts of Meteor’s API layer functionalities. One of them is Feathers.js, but it’s mainly focused on ‘just’ the API client / server part. Another one is RxDB, but I see that one more as a replacement for Meteor’s DDP, Methods and Minimongo integration. Again, just 1 part of the total picture.
The choice is up to you, but if your focus needs to be on features, I would choose Meteor. If you require only the UI part with very powerful features and things like static rendering, use Next. (That is if you decided that React is your tool of choice)
Top comments (8)
you can add the apollo server directly into nextjs using its api route. Its very simple: github.com/vercel/next.js/tree/can...
About breaking changes in react: I feel quite the opposite: despite the changes in how to build components (createComponent -> es classes -> functional components with HOCs and now functional components with hooks), there were never big breaking changes. deprecated features were marked early as such and where exported in their own packages and communication was always very good. So even today you can use react like in the early days (altough i would not recommend it). Also its ecosystem is very alive and many important packages have been updated to work with latest version of react.
I agree with everything you say. Both Next and other framework ecosystems are growing with fantastic tools. Like I said I'm a huge fan Next and Nuxt. But these tools are the apples. You will have to pick them yourselves.
However since React and Next on themselves have a small API service and therefore require many 3th party tools to work. This leads to problems and one of these problems was React Router's switch from 3 to 4. Another big one is the movement away from class based components into functional components which forced an entire community to switch to the functional paradigm. Many devs I know had major issues when switching and now need to refactor or even rebuild entire modules, because they were build during this transition phase. To give an impression. React went from:
Admitted the Apollo Server with API routes is very powerful, but it does still not solve managing domain state on the UI, realtime capabilities, synchronizing with a database and optimistic UI. These are all things that you will need to do yourself and its quite complex to do so
why should apollo not solve managing domain state on the ui? (i agree with realtime capabilities though). apollo client is management of the domain state. Also it supports optimistic ui, altough not that magically like meteor's pub/sub
Also I think forcing the database to the client is an anti-pattern (altough convenient in simple case). I like the additional layer that graphql provides so that client and server can agree on a common contract (= the graphql schema).
minimongo was very cool, like magic, but t has its limits and stretching it beyond its limits is not a good idea.
It does and it should. It's just not without having to build boilerplate or 3th party packages. Again I love Apollo, but it's still not on a level that is as intuitive as Meteor has
It's a pattern that is considered defacto on native apps. Android has SQLite, Apollo essentially is a "database-ish" implementation. RxDB is a clientside database. Redux could be a domain database too, but it does not have the tooling to properly query and manage it.
In fact all implementations that have some form of collection or list that comes from the server is kind-off a subset of the original dataset and thus it would be logical to be able to query this subset from within different components. That's why Apollo has useQuery - which is the equivalent of Minimongo's Collection.find(selector).
Every tool has its purpose. I agree on this point. Minimongo makes less sense for a simple blog, but so does Apollo Client and even any dynamic site given that modern static site generators provide us with much better tools.
Maybe you could also take a look at vulcanjs.org/. We're based on Meteor but trying to move in a more Meteor-agnostic direction by embracing GraphQL (while making it as simple to use as Minimongo is).
What exactly you mean by that? There are too few things in software development that are black-and-white when it comes to word "wrong".
So far, my main issue with Apollo was the absence of clear integration points with MobX (entities in Apollo client cache + MobX's computed fields)... Otherwise, Apollo seems usable and doesn't look too "wrong" in our code bases.
Also, React itself does not bring reverse compatibility issues. The shift from classes to functional components is not forced upon anybody.
That link doesn't work anymore.
How could we access that knowledge?
Have you tried CouchDB together with PouchDB client which I call "NoBE" stack, since you have direct access to the database API?