Hot Code Push, step by step
source link: https://blog.meteor.com/hot-code-push-step-by-step-bd940de7323c
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Hot Code Push, step by step
This is a guest post by Bart Sturm, co-founder of TutorMundi, a Brazilian on-demand tutoring app.
Hot Code Push is one of my favorite features of Meteor.
It’s amazing to be able to push new versions of your app to all users across all devices and platforms at once.
Though as a bridge between several different technologies with many moving parts, it doesn’t always work seamlessly. When you realize it’s not working reliably in your app, what can you do?
Common issues and solutions
Let’s not reinvent the wheel — let’s start with some time-tested solutions:
How to dig deeper
But what if none of these solve your particular issue?
Then let’s start looking at your client side logs.
Of course, you may find the cause of your issue right then and there.
If not, that’s okay — we’re about to start logging a whole lot more. We’re going to follow Hot Code Push every step on the way.
(Note: I shared similar code samples in the Meteor Guide. Also, the libraries Tracker and lodash used here are helpful but not necessary. )
Step 1. Server creates new client hash
Whenever the server thinks the client side may have changed, it calculates a hash of your entire client bundle. We can log the following both on the server and client, and compare:
__meteor_runtime_config__.autoupdate.versions['web.cordova']
Step 2. The client subscribes to new hashes
The server publishes this hash to all clients. The clients subscribe to this publish.
To check the status of our subscription, we can log this in the client:
Meteor.default_connection._subscriptions
This shows lots of information about each of your subscriptions. For more readable output, I like to select the subscription I’m interested in and pick some specific properties. For example:
const { ready, inactive } = _.chain(Meteor)
.get('default_connection._subscriptions', {})
.toPairs()
.map(1)
.find({ name: 'meteor_autoupdate_clientVersions' })
.pick(['inactive', 'ready'])
.value();
console.log(‘ready:’, ready);
console.log(‘inactive:’, inactive);
We can modify this a bit to check the status of the subscription every time the subscription changes (for example, when ready
goes from false
to true
):
const hcpSub = _.chain(Meteor)
.get('default_connection._subscriptions', {})
.toPairs()
.map(1)
.find({ name: 'meteor_autoupdate_clientVersions' })
.value(); // no .pick() this time; return whole object
Tracker.autorun(() => {
hcpSub.readyDeps.depend(); // Rerun when the subscription changes
console.log('hcpSub.ready', hcpSub.ready);
});
Step 3. A new client hash arrives
If the client receives client hashes different from its own, our Cordova app starts downloading the new version. (On web, the download only occurs after the reload; our Meteor app is simply a website after all.)
At this point the reactive Autoupdate.newClientAvailable()
will start returning true
:
Tracker.autorun(() => {
console.log(Autoupdate.newClientAvailable());
});
Step 4. (Cordova only): the new version was downloaded
On mobile, when the new version is downloaded, Meteor will trigger the callback passed to WebAppLocalServer.onNewVersionReady
. There can only be one such callback. To log this step without breaking the next, our code can define a new callback that adds logs and then add the code from the original. At the time of writing, it looks like this:
WebAppLocalServer.onNewVersionReady(() => {
console.log('new version is ready!');
// Copied from original in autoupdate/autoupdate_cordova.js
if (Package.reload) {
Package.reload.Reload._reload();
}
});
Step 5. Ask for permission to reload
The client will now announce that it will reload. The app and packages get a chance to save their data or to deny or delay the reload. To find out if this point is reached, we can add a callback to _onMigrate
:
Reload._onMigrate(() => {
console.log('going to reload now');
return [true];
});
Step 6. Reload
If every Reload._onMigrate
callback grants permission, the app reloads.
As part of this, all startup
callbacks are run again. To know whether a startup was the result of a Hot Code Push or simply of opening the app, we could use a Session
variable, which are preserved across Hot Code Push updates:
Meteor.startup(() => {
console.log('Was HCP:', Session.get('wasHCP'));
Session.set('wasHCP', false);
Reload._onMigrate(() => {
Session.set('wasHCP', true);
return [true];
});
});
Going further
Want to know more? The new Hot Code Push article in the Meteor Guide explains this topic in more depth.
Hot Code Push is at its most powerful when you can rely on it without any doubts. I hope these articles help you solve your own Hot Code Push issues so you can speed up your development cycle and focus on serving your customers.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK