Where does Meteor stand on progressive enhancement?

I’m currently learning Meteor as a beginner. And I’m loving the experience.

However I became slightly worried when I discovered that meteor.com itself, and its example apps, display no content with JavaScript disabled in the browser.

Where does Meteor stand on progressive enhancement? I can only imagine very few apps that are pure “interaction”. The apps I’m dreaming of building have content. Content that ideally is accessible to everyone, and at all times.

I would love to hear some opinions on this. Especially from Meteor core.

If your users will disable JavaScript in their browsers, Meteor is just not for you :wink:

Gov.uk found that out of 500 visitors 5 did not receive JavaScript, but only 1 had JavaScript disabled (source: How many people are missing out on JavaScript enhancement?). So it’s not always that simple. Not to mention third world countries where sometimes JavaScript is simply not an option.

Nowadays that’s like turning off the water supply to your home to save on the water bill and then requesting your landlord to provide someone to walk back and forth to the lake with a bucket because you ofcourse still want to be able to take showers.


From the Meteor docs:

… the best teams, with the biggest budgets and the longest schedules, now build applications in JavaScript that run on the client. These apps have stellar interfaces. They don’t reload pages. They are reactive: changes from any client immediately appear on everyone’s screen.

These are JavaScript applications. Period.

1 Like

I feel it’s more like building an escalator instead of an elevator. When the escalator breaks it’s still useful.


Even though I find it totally silly impractical to build a Meteor application for browsers that do not want to run JS, I wouldn’t find it too hard to build a content heavy app where everything gets rendered on the server and sent to the client.

I even have some server side routes that display plain text for debugging reasons. Not a single HTML tag is in the source code of those pages so that proves that you don’t need client side js to display words on a screen with Meteor.

As simple as

Router.route('/server/post', {
    action:function(req, res){
        res.end(YourHTMLGenerator(template, PostCollection.find(1)));
    where: 'server'

Reactivity of course gets thrown out of the window, and I don’t see a single reason why you would choose Meteor for such an app but you can do so. Like you can use the rocket of a nuclear warhead to propel a bicycle.


Careful design (adding the spiderable package, using server side rendering or an external service like prerender.io) means that static HTML can be made available (e.g. for crawlers). However, the whole ethos of Meteor is to provide highly interactive, client-server web applications. You can’t have both, or at least not without consequences.

1 Like

I’m not arguing against JavaScript applications. Surely it must be possible to render some version of the content server-side to provide as a fallback.

From the Meteor mission:

[Meteor] should be accessible to the maximum number of people.

If you have a horse it could be reasonable to maintain a pony as a backup.

If you have a car, is it still reasonable to maintain a horse as a backup? Even when pretty much everything you use that car for is impossible with a horse anyway?

If you’re saying that indeed a horse could do what your car is for, then perhaps you should have gotten a horse from the start instead of a car.


Great share. I think for the sake of progressive enhancement this is they way to go. Providing a dumbed down version of your app for browsers that don’t have JS, and doing it from within your metor app so that you don’t need to maintain a totally separate app/framework just to say, “Hey you’ll get a better experience with JavaScript”.

Sure, at least a message informing the user they need JavaScript to use your app. But to be able to use your Meteor app without JavaScript, you might as well write your app in PHP.

I think questions like this are an important part of choosing a framework. If you really need to support users without JavaScript, maybe Meteor isn’t the right framework for your project.


JavaScript is now a permanent technology of the web. Running your browser with JavaScript disabled is like running GarageBand without an audio interface. Less than 1% of users have JavaScript disabled. And a portion of that 1% isn’t even humans sitting behind an intentionally JavaScript-disabled browser–I suspect most of them are bots but it can be attributed to things like corporate firewall filters, mobile network errors.

Users who do turn JavaScript off are used to things breaking for them.

Progressive enhancement is ideal, but it only actually works if the fallback would be useful, and in the case of many web apps - it isn’t.

I wouldn’t be too concerned about things breaking with JavaScript turned off. In 2015, it isn’t worth the overhead to support this minority. Its like trying to design your smartphone app to work well for the minority of thumb-amputees. The effort spent in refactoring your code for graceful degradation could be spent on improving other functionalities used by a wider audience.


Thought more about it. Here’s some additional thoughts.

“Progressive enhancement” was an notion relevant to an earlier generation of web applications. Traditional web frameworks treat the internet like a souped-up fax machine. Pages were cooked up on the server and the presentation sent over HTTP to the dumb-terminal-like client. The problem has always been that HTTP was the wrong protocol for the web. It’s stateless, session-less, and basically uni-directional. For decades in enterprise we’ve had rich desktop clients which consumed data sent over the wire using stateful, bi-directional protocols (RPC).

We’ve been working around HTTP for over 20 years. Like adding JavaScript to handle client-side data validation so that we didn’t have to make a round-trip to the server, because re-rendering the whole page was so slow and inefficient. Then we added things like AJAX so that we could load in bits of data at a time, like populating the cities for a selected country.

What makes Meteor so revolutionary is that they’ve address the fundamentals of these issues rather than continuing to workaround them. DDP is everything that HTTP isn’t. It’s provies session-based, stateful, bi-directional communication between your app and server allowing the app to me located closer to the user, rather than centralized on the server like in mainframe architecture. You see this same approach taken in native mobile apps–the rich client app runs on the phone and only bit of data are sent back and forth over the wire. Client/server development in enterprise has been doing this for decades.

This is another matter entirely but Meteor also elegantly addresses the single biggest difficulty in developing web apps, which is keeping data in sync between clients and the server. In a traditional framework like Rails you might use ajax to load some data into the client for presentation. You might store it somewhere like in HTML5 cache or in a backbone collection. Then once the user modifies it, you’ll need to see if something change on the server and figure out how to handle that situation. You do this on an ad hoc basis in those frameworks.

Meteor solves the problem of keeping data in sync between the client and server by making the data you need transparently available everywhere. In the client the data is stored in a database (holy shit!) which you can query–a far cry from a simple static array or collection. The data you need it loading into that collection for you, changes to that data are instantly reflected in the client (reactive templates) and pushed to the server for you. And changes on the server are pushed down to your app (with templates reacting accordingly).

This kind of experience (for both the client and the developer) is often well worth some start up lag. I’d rather move forward and figure out smarter ways to improve application loading (cdn, rendering optimizations, progressive fragment loading, pre-loading data) than go back. We’ll be helped along as processors and transmissions speeds improve, and I think just as people are used to waiting a moment for their mobile app to load, they will get accustom to waiting a moment for a rich web app to load (a la Slack, Asana, Google Docs, Trello, Pivotal Tracker, etc.). These apps can be slow to start but very snappy once loaded, and they offer a new level of near real-time collaboration and reactivity without having to hit the refresh button like traditional web development frameworks. After working with Meteor for more than two years I’m flabbergasted why so many apps require a refresh before you see data changes. It’s so easy to development them in Meteor to be reactive.

Also many sites like blogs should load as fast as any PHP site since there isn’t a whole lot of template logic to load in the first place.

Of course we care about performance too. Our many small Meteor apps are quick to load, but we are in the process of splitting a large application in two. The idea is to separate in-house (backoffice) features from customer-facing features. Both apps will connect to the same database, but no sense in sending features down the wire to the client that they don’t have permission to use them anyway. Probably 80% or more of the code is for our backoffice team, so the client interface is going to be very light after our refactoring.

Meteor is still very young (version 1.1) and getting better all the time. The community is actively working to address these issues and some solutions already exists. Like fast-render and spiderable packages.

Progressive enhancement basically seems to assume a paradigm in which JavaScript is just a bit player used for enhancements to the interface and nothing too important. But those days are over for many of us, and progressive enhancement is dead.


I’m not convinced that JS “breaks”. A while back the download button didn’t work on the Google Chrome page. Some “progressive enhancement” priests howled about how this shouldn’t happen if they only followed the PE doctrine. But I don’t believe that JS failed. Probably someone got the link wrong, the file was missing, or someone made a programming mistake. JS probably did exactly was it was suppose to do; the programmers and testers didn’t.

A test should have been written, but of course it’s hard to write tests for all cases. But that’s not an endorsement for progressive enhancement, because your PE fallback link could just as easily be malformed or the file uploaded to the wrong folder.

Escalators can break too in ways which are not beneficial

Thanks for a nice write-up Max. Appreciate it!

1 Like