Announcing the Capacitor Live Update Plugin¶
One of the biggest advantages of Capacitor over other runtimes is the ability to deliver updates in real-time without having to resubmit your app to the app stores, so-called Over-the-Air (OTA) updates. For this reason, we are very excited to introduce you today to our brand new Capacitor Live Update plugin. In this blog post, you will learn everything about the new plugin and how you can implement it in your Capacitor app.
How it works¶
Live updates are a powerful feature that allows you to deliver small bug fixes and updates to your Capacitor app in real-time. For this, it is important to understand the different layers of a Capacitor app and how they interact with each other.
As you can see in the image above, a Capacitor app basically consists of a web layer and a native layer. The web layer consists of the HTML, CSS, and JavaScript files that are loaded into the web view. The native layer consists of the native code that is compiled into the app.
Limitation
Live updates only allow you to update the web layer of your app.
So as long as you only make changes to your web application, you can deploy live updates without having to resubmit your app to the app stores. As soon as you make a change to the native code, such as adding a plugin, you must resubmit your app to the app stores.
Installation¶
First you need to install the package and sync your Capacitor project:
Usage¶
To be able to distribute the live updates to your users, you need to host a service that at least provides the bundles for download. You can either self-host such a service or use the Capawesome Cloud. Let's take a look at the self-hosted option first.
Self-hosted¶
If you choose the self-hosted option, you have to make sure that your bundle is available for download somewhere.
To download a bundle, you need a public URL and a unique bundle ID. The bundle ID is only used to identify the bundle and can be chosen freely.
Use the downloadBundle(...)
method to download a bundle:
import { LiveUpdate } from '@capawesome/capacitor-live-update';
const downloadBundle = async () => {
await LiveUpdate.downloadBundle({
url: 'https://example.tld/1.0.0.zip',
bundleId: '1.0.0',
});
};
The plugin then downloads, extracts and moves the bundle to the correct location.
Binary Compatible Changes
Make sure that you implement a mechanism that ensures that only Binary Compatible Changes are delivered to the users to prevent incompatible updates. For example, the Capawesome Cloud offers the possibility to use Channels to restrict updates to specific versions of your app.
After downloading the bundle, you can set it as the next bundle (1) to use with the setBundle(...)
method.
This means that the next time the app is started, the new bundle will be used.
- The next bundle is the bundle that will be used the next time the web view is loaded. This allows you to download and prepare a new bundle without immediately applying it. This way you can ensure that the new bundle is only used after a restart of the app or a reload of the web view.
import { LiveUpdate } from '@capawesome/capacitor-live-update';
const setBundle = async () => {
await LiveUpdate.setBundle({ bundleId: '1.0.0' });
};
If you want to apply the next bundle immediately, you can use the reload()
method to reload the web view.
import { LiveUpdate } from '@capawesome/capacitor-live-update';
const reload = async () => {
await LiveUpdate.reload();
};
To make sure that your app does not break if you set an incompatible bundle, the plugin provides an automatic rollback mechanism.
This rollback mechanism resets the bundle to the bundle with which the app was delivered.
To prevent a rollback, you must call the ready()
method as soon as the app is ready.
import { LiveUpdate } from '@capawesome/capacitor-live-update';
const ready = async () => {
await LiveUpdate.ready();
};
After calling the ready()
method, the app is considered ready and the automatic rollback mechanism is disabled.
Cloud¶
If you don't want to host such a service yourself or if you want to use additional features such as Channels or Rollouts, you can use the Capawesome Cloud to upload, manage and distribute your bundles. To get started, you need to create an account on the Capawesome Cloud Console.
After you have created an account, we recommend that you install the Capawesome CLI to manage your apps and bundles from the command line.
First, you need to log in to Capawesome Cloud:
Then you can create a new app:
After you have created an app, you need to configure the Capacitor Live Update plugin. To do this, simply add the ID of the app you have just created to the Capacitor configuration file:
{
"plugins": {
"LiveUpdate": {
"appId": "00000000-0000-0000-0000-000000000000"
}
}
}
Sync your Capacitor project to apply the changes:
Next, you can upload a new bundle to the Capawesome Cloud.
For this, you simply need to specify the path to the bundle (e.g. www
or dist
) and the ID of the app (see previous step):
Upload to a channel
We recommend that you also specify a Channel when uploading the bundle:
This way you can easily restrict live updates to native versions of your app and prevent incompatible updates.
The Capawesome CLI then automatically creates a zip archive of the bundle and uploads it to the Capawesome Cloud where it becomes immediately available for download.
All that's left to do is to call the sync()
method in your app to check for new updates and apply them if necessary.
import { LiveUpdate } from '@capawesome/capacitor-live-update';
const sync = async () => {
const result = await LiveUpdate.sync();
if (result.nextBundleId) {
await LiveUpdate.reload();
}
};
The new bundle becomes available only after restarting the app.
Therefore, if you want to apply the new bundle immediately, you should call the reload()
method to reload the web view.
Again, make sure to call the ready()
method as soon as the the app is ready to prevent a rollback:
import { LiveUpdate } from '@capawesome/capacitor-live-update';
const ready = async () => {
await LiveUpdate.ready();
};
Testing¶
When testing the plugin, you must make sure that you do not use the Live Reload option, as in this case a development server is used to load the bundle.
Therefore, simply start your app without the live reload option, for example with the following command:
As soon as you have installed a live update, the app will use the live update bundle and no longer the default bundle.
So if you make local changes to your app and execute npx cap run
, for example, these changes will apply to the default bundle, which is not currently in use.
You then have three options to get back to the default bundle:
- Reset: Call the
reset()
method to reset the app to the default bundle. - Reinstall: Reinstall the app to use the default bundle.
- Update: Increase the
versionCode
/CFBundleVersion
so that the plugin automatically performs a reset (assuming theresetOnUpdate
configuration option is active).
However, this is only a problem during development. It is not a problem in production as long as you have the resetOnUpdate
configuration option enabled, as the versionCode
/CFBundleVersion
is always incremented during a native update and thus always resets to the default bundle.
Closing Thoughts¶
We hope you are as excited as we are about the new Capacitor Live Update plugin. We are already working on new features and improvements, such as automatic update modes and partial updates. Be sure to check out the API Reference to see what else you can do with this plugin. If you have any questions, just create a discussion in the GitHub repository. Make sure you follow us on X so you don't miss any future updates.