NativeScript AppSync 插件使用指南

Viewed 0

NativeScript AppSync Plugin

A live-update service for your NativeScript apps!

Note: NativeScript AppSync is currently in beta and is not supported by the core NativeScript team. It is based on Microsoft CodePush, and we thank them for their work.

Optional reading: what this is and how it works. A NativeScript app is composed of XML/HTML, CSS, and JavaScript files along with images, bundled by the NativeScript CLI into platform-specific binaries like .ipa or .apk files. Once released, updating code or assets requires recompiling and redistributing the entire binary, which involves app store review times.

The AppSync plugin addresses this by synchronizing code and images with updates released to the AppSync server. This allows instant updates for end users, combining offline mobile experience with web-like agility. It ensures a functioning app by maintaining a copy of the previous update for automatic rollback in case of crashes, providing release agility without blocking users.

What can (and will) be AppSync'ed?

  • Anything inside your /app folder (but not the App_Resources folder).
  • Anything inside your /node_modules folder.

Note that we don't actually use those folders directly, but the compiled assets in platform-specific directories, so tools like Webpack or Uglify are transparent.

What can't (and won't):

  • NativeScript platform updates (e.g., bumping tns-android versions).
  • Plugin updates that require different native library versions.
  • Contents of the App_Resources folder, as they are part of the native binary.

As long as you don't change dependency or platform versions in package.json, you can push updates freely. If you do bump a version, ensure no native libraries are altered.

Getting Started

Globally install the NativeScript AppSync CLI

npm i -g nativescript-app-sync-cli

This adds the global nativescript-app-sync command. Check the version with nativescript-app-sync -v.

Login or register with the service

Check if logged in:

nativescript-app-sync whoami

Log in if you have an account:

nativescript-app-sync login

Register if new:

nativescript-app-sync register

This opens a browser for credentials, after which you can create an access key. A .nativescript-app-sync.config file will be created in your home folder for automatic authentication.

To log out, run nativescript-app-sync logout, which removes the config file. For headless login, use nativescript-app-sync login --accessKey <access key>.

Register your app with the service

Create an app for each platform (iOS and Android) to allow separate rollouts:

nativescript-app-sync app add <appname> <platform>
# examples:
nativescript-app-sync app add MyAppIOS ios
nativescript-app-sync app add MyAppAndroid android

The appname must be unique and without dashes. This shows deployment keys needed for connecting to the AppSync server. List keys later with nativescript-app-sync deployment ls <appName> --displayKeys.

New apps automatically have two deployments (Staging and Production). Add more with nativescript-app-sync deployment add <appName> <deploymentName>.

To rename an app, use nativescript-app-sync app rename <oldName> <newName>. To delete, use nativescript-app-sync app remove <appName>.

List your registered apps

nativescript-app-sync app ls

Add this plugin to your app

tns plugin add nativescript-app-sync

If restricting internet access in your app, whitelist the AppSync server (https://appsync-server.nativescript.org) and file server (https://s3.eu-west-1.amazonaws.com).

Checking for updates

With the plugin installed, add code to control update checks. Updates are silently downloaded and installed based on the InstallMode:

  • InstallMode.ON_NEXT_RESTART: Updates on next cold start (default).
  • InstallMode.ON_NEXT_RESUME: Updates on next resume.
  • InstallMode.IMMEDIATE: Shows a prompt for immediate installation (use cautiously on iOS for AppStore apps).

Apple discourages prompting users to restart apps, so use IMMEDIATE only for Enterprise distributions or TestFlight testing.

Example TypeScript code:

import { AppSync, InstallMode, SyncStatus } from "nativescript-app-sync";
import { isIOS } from "tns-core-modules/platform";

AppSync.sync({
    enabledWhenUsingHmr: false,
    deploymentKey: isIOS ? "your-ios-deployment-key" : "your-android-deployment-key",
    installMode: InstallMode.ON_NEXT_RESTART,
    mandatoryInstallMode: isIOS ? InstallMode.ON_NEXT_RESUME : InstallMode.IMMEDIATE,
    updateDialog: {
        updateTitle: "Please restart the app",
        optionalUpdateMessage: "Optional update msg",
        mandatoryUpdateMessage: "Mandatory update msg",
        optionalIgnoreButtonLabel: "Later",
        mandatoryContinueButtonLabel: isIOS ? "Exit now" : "Restart now",
        appendReleaseDescription: true
    }
}, (syncStatus: SyncStatus, updateLabel?: string): void => {
    console.log("AppSync syncStatus: " + syncStatus);
    if (syncStatus === SyncStatus.UP_TO_DATE) {
        console.log(`AppSync: no pending updates; latest version is ${updateLabel}`);
    } else if (syncStatus === SyncStatus.UPDATE_INSTALLED) {
        console.log(`AppSync: update installed (${updateLabel}) - activates on next cold boot`);
    }
});

JavaScript example:

var AppSync = require("nativescript-app-sync").AppSync;
var InstallMode = require("nativescript-app-sync").InstallMode;
var SyncStatus = require("nativescript-app-sync").SyncStatus;
var platform = require("tns-core-modules/platform");

AppSync.sync({
    enabledWhenUsingHmr: false,
    deploymentKey: platform.isIOS ? "your-ios-deployment-key" : "your-android-deployment-key",
    installMode: InstallMode.ON_NEXT_RESTART,
    mandatoryInstallMode: platform.isIOS ? InstallMode.ON_NEXT_RESUME : InstallMode.IMMEDIATE,
    updateDialog: {
        optionalUpdateMessage: "Optional update msg",
        updateTitle: "Please restart the app",
        mandatoryUpdateMessage: "Mandatory update msg",
        optionalIgnoreButtonLabel: "Later",
        mandatoryContinueButtonLabel: platform.isIOS ? "Exit now" : "Restart now",
        appendReleaseDescription: true
    }
}, function (syncStatus, updateLabel) {
    if (syncStatus === SyncStatus.UP_TO_DATE) {
        console.log("AppSync: no pending updates; latest version is: " + updateLabel);
    } else if (syncStatus === SyncStatus.UPDATE_INSTALLED) {
        console.log("AppSync: update (" + updateLabel + ") installed - activates on next cold boot");
    }
});

When should this check run?

It's recommended to check for updates multiple times per cold boot cycle, such as tying to the resume event (which runs on app startup):

import * as application from "tns-core-modules/application";
import { AppSync } from "nativescript-app-sync";

application.on(application.resumeEvent, () => {
    AppSync.sync(...);
});

JavaScript:

var application = require("tns-core-modules/application");

application.on(application.resumeEvent, function () {
    // call the sync function
});

Releasing an update

After making code or asset changes, release updates using the AppSync CLI. First, create a release build as for app store distribution (without submitting). Key options for the release command:

  • deploymentName (alias d): Default "Staging". Deploy to "Staging" or "Production".
  • description (alias des): Description of changes.
  • targetBinaryVersion (alias t): Semver expression targeting binary app versions (default from Info.plist or AndroidManifest.xml).
  • mandatory (alias m): Marks the update as urgent (e.g., critical fix).

Examples for iOS:

nativescript-app-sync release <AppSync-ios-appname> ios
nativescript-app-sync release <AppSync-ios-appname> ios --d Production
nativescript-app-sync release <AppSync-ios-appname> ios --targetBinaryVersion ~1.0.0
nativescript-app-sync release <AppSync-ios-appname> ios --mandatory --description "My mandatory iOS version"

Examples for Android:

nativescript-app-sync release <AppSync-android-appname> android
nativescript-app-sync release <AppSync-android-appname> android --d Production
nativescript-app-sync release <AppSync-android-appname> android --targetBinaryVersion ~1.0.0

The targetBinaryVersion specifies which binary versions receive the update, using semver ranges (e.g., 1.2.3, *, ~1.2.3). Wrap values in quotes for special characters.

Gaining insight in past releases

Use CLI commands to view release history and metrics.

View install metrics:

nativescript-app-sync deployment history <appsync-appname> Staging

This shows release labels, times, versions, mandatory status, descriptions, and install metrics (active and total installations).

View current release details:

nativescript-app-sync deployment ls <appsync-appname>

Add --displayKeys to show deployment keys.

Clear release history metadata (does not roll back releases):

nativescript-app-sync deployment clear <appsync-appname> Staging

Advanced topics

Testing AppSync packages during development

Test updates before production:

  1. Run tns run <platform> (on iOS device, add --release to avoid LiveSync interference).
  2. After update installation, kill and restart the app.

Running the demo app

Observe updates using the demo app:

  1. Register with the service and add the demo app.
  2. Update deployment keys in the demo code.
  3. Build the plugin and demo app.
  4. Prepare an update version and release it.
  5. Run the official release version on a device.
  6. Restart the app to see the update applied.

Patching Update Metadata

Modify metadata of a released update (e.g., mark as mandatory):

nativescript-app-sync patch <appName> <deploymentName> [--label <releaseLabel>] [--mandatory <isMandatory>] [--description <description>] [--targetBinaryVersion <targetBinaryVersion>]

Example:

nativescript-app-sync patch MyAppiOS Production -m
nativescript-app-sync patch MyAppiOS Staging -t "1.0.0 - 1.0.5"

This doesn't modify update contents; use rollback for broken releases.

Promoting Updates

Promote releases from one deployment to another (e.g., Staging to Production):

nativescript-app-sync promote <appName> <sourceDeploymentName> <destDeploymentName> [--description <description>] [--label <label>] [--mandatory] [--targetBinaryVersion <targetBinaryVersion>]

Example:

nativescript-app-sync promote AppSyncDemoIOS Staging Production --description 'Promoted from Staging to Production'

This creates a new release in the destination deployment with the same code and metadata as the latest source release, ensuring consistency.

Rolling Back Updates

Roll back a broken or unintended update:

nativescript-app-sync rollback <appName> <deploymentName>

Example:

nativescript-app-sync rollback MyAppiOS Production

This creates a new release reverting to the previous version. Use --targetRelease to roll back to a specific release.

Rollbacks are annotated in the release history.

App Collaboration

Add collaborators to an app:

nativescript-app-sync collaborator add <appName> <collaboratorEmail>

Collaborators can view the app, release updates, and roll back deployments, but cannot rename/delete the app, manage deployments, or modify collaborators.

Remove a collaborator:

nativescript-app-sync collaborator rm <appName> <collaboratorEmail>

List collaborators:

nativescript-app-sync collaborator ls <appName>

Using AppSync behind a proxy

By default, the CLI uses system-wide proxy settings from HTTPS_PROXY or HTTP_PROXY environment variables. Disable with --noProxy:

nativescript-app-sync login --noProxy

Specify a proxy explicitly:

nativescript-app-sync login --proxy https://foo.com:3454

Proxy settings persist with the user session.

Troubleshooting

  • Build errors related to nativescript-zip plugin? Check the solution in the linked issue.
0 Answers