Blaze 3 with Meteor 2.1x

I can’t overstate the importance and my appreciation of @rakekmie [On Asynchronicity in Blaze (again) · @radekmie’s take on IT and stuff] work.

I use isomorphism extensively - not just with Meteor methods (e.g. collection helpers). So almost all my 750+ HTML files will be subject to many asynchronous helper methods - having them seamlessly react appropriately is essential!

As I transition my code to be Meteor 3 compatible, I remain on Meteor 2.1x. That way my app works and I can keep testing. If I upgrade to Meteor 3, server-side breaks. But now my client-side is breaking down due to not having your changes. So my conversion is more and more relying on unit tests.

Question: Can Blaze 3 by released/used in a Meteor 2.1x version?

Many thanks

1 Like

And have you tried it maybe? It was meant to be possible, so if it’s not, then we have to fix it. All of the async changes in Blaze are not breaking backward compatibility (well, they are if you assume that weird behavior with Promises was correct) and were merged to the current version, not 3.x.

Hi @radekmie , Thank you for the reply - I was rudely assuming your updates are not in the latest Meteor releases (I am on 2.13.3). Or do I need 2.14?

What great work to make it all backward compatible. Is it the intention that all references to functions in Blaze will use the resolved values seamlessly (and withhold rendering appropriately until then), including dot sequences?

So “all” I need to do is await/async my helpers as needed?

Blaze is versioned separately, so it shouldn’t be a problem. I think the latest changes are not released yet, though (see this Slack thread).

Thanks @radekmie , at the risk of appearing pedantic can you comment on the following 3 scenarios regarding Meteor 3 with Blaze and respond to my subsequent 2 questions?

Assuming this HTML:

<div>{{getDocument.name}}</div>

Scenario 1

In helper JS file:

Template.example.helpers({
    getDocument() {
        return mongoCollection.findOne();
    }
}

Good times … No changes necessary in Meteor 3 as this is all client side and FindOne() continues to work synchronously.

Scenario 2

In isomorphicFile.js:

export const getDocument=async function() {
    return await mongoCollection.findOneAsync();
}

Having necessarily converted as we use this function on the server.

In helper JS file:

import {getDocument} from '/folder/isomorphicFile.js';

Template.example.helpers({
    getDocument() {
        return getDocument();
    }
}

More good times … Blaze 3 happily deals with a Promise which is passed through by this unchanged helper code.

Scenario 3

In helper JS file:

import {getDocument} from '/folder/isomorphicFile.js';

Template.example.helpers({
    getDocument() {
        let document=getDocument();
        if (document.preference==='I like') return document;
        else return {name: 'No likey'}
    }
}

Sad times, I would have to convert this helper function to, say:

import {getDocument} from '/folder/isomorphicFile.js';

Template.example.helpers({
    async getDocument() {
        let document=await getDocument();
        if (document.preference==='I like') return document;
        else return {name: 'No likey'}
    }
}

So assuming your agreement with the above I have two specific questions:

  1. Is Blaze 3 sufficiently async friendly that I should expect to make no changes to my HTML Blaze templates? If not, in which circumstances would an async helper not work? Put another way, could I blindly change all my helpers to async and expect everything to work (I won’t) in Blaze?

  2. Does the reactivity continue to work as expected in Scenarios 2 & 3? I.e. if the retrieved document changes, then Blaze works it out through the promises and re-renders? Fantastic if you managed that as I can’t get my head around how! If not, then I’ve got problems …

Thank you

  1. I’d say “good times” :stuck_out_tongue: Yes, to unpack the document from getDocument, you’ll need to add await there. But the way you did it is enough – no changes in the .html file are needed.
  2. Yes, it will, but there are some limitations. See documentation of Tracker.withComputation (essentially all Blaze helpers are wrapped in Tracker.autorun). You can read more in 💫 Additional Async Transition Documentation and in 🔥 The current state of Blaze & Async - Or: everything I learned about Blaze and Async in the last 6 Months.
1 Like

Thank you @radekmie ,

@dthwaite just one thing: before you jump into the link " :fire: The current state of Blaze & Async - Or: everything I learned about Blaze and Async in the last 6 Months".

That post is a bit outdated by now and I haven’t gotten around to really updating it. I’ll probably focus more on the “transition docs” in google docs here: How to convert your existing Meteor App to ASYNC & Prepare for Meteor 3.0

Which also isn’t 100% up to date, for example there’s a solution which seems to be working, at least for us, for client side stubs now (or actually maybe even two): The zodern:fix-async-stubs package & another solution by @alisnic , all to be found in this thread: [ Proposal to fix issues with async method stubs](Proposal to fix issues with async method stubs - #7 by rjdavid). Also @radekmie fixed the async attributes in the blaze templates too, which is awesome

But I really want to focus on is the Babel Plugin we developed to help out with your issue number 2: :pizza: Blaze / Async Migration Helper: Babel Plugin Tracker-Async-Enhance for the Client Side released
Which basically wraps all await calls in the client with Tracker.withComputation and makes sure the current computation is passed through in reactive contexts.

It’s not perfect, but it runs well enough for us in a large production app.

1 Like

Thanks @DanielDornhardt,

I’ve removed my last post as I had panicked about no reactivity at all for async functions thinking your plugin was necessary in all cases. I now understand that reactivity will work with provisos as @radekmie warns and mitigated with Tracker.withComputation(). I appreciate the babel plugin, but my current approach is to do everything manually as this allows me to refactor appropriately each time and is also giving me an opportunity to build up test scripts.

It’s a lot of work.

Hi @dthwaite !

It can be a lot of work, but fortunately it’s just work and nothing impossible. Panic never helps, but I know it can feel very stressful sometimes being responsible for an app like this :slight_smile:

The Babel Plugin is useful if you have a lot of code which runs on both server and client which you expect to stay fully reactive on the client too.

That’s mostly important for certain blaze projects who use a lot of shared code for logic and validation between client + server where it’s not easy to pass around a computation object everywhere and you don’t want to wrap a lot of lines with Tracker.withComputation manually.

Understood, and thanks again.

I do have a lot of shared validation as you say, but as I tackle all this one by one, it may be that reactivity is only really necessary for a primary document selection and I can weather secondary ones - though this so often has, in the past, pleasantly surprised me how changes bubble up into the UI above expectations! Your plugin is certainly a good fallback if the going gets tough!

1 Like