- 版本:2.0.2
- GitHub: https://github.com/eddyverbruggen/nativescript-code-push
- NPM: https://npmjs.net.cn/package/nativescript-code-push
- 下载
- 昨天: 0
- 上周: 4
- 上个月: 30
NativeScript 的 CodePush 插件
为您的 NativeScript 应用程序提供实时更新服务!
📣 更新 2019 年 5 月 27 日:在官方发布之前,我们很可能会更改此解决方案的名称。请耐心等待!
可选阅读:这是什么,以及它是如何工作的
NativeScript 应用程序由 XML/HTML、CSS 和 JavaScript 文件以及任何相关图像组成,这些文件由 NativeScript CLI 打包并作为平台特定二进制文件(即 .ipa 或 .apk 文件)的一部分进行分发。一旦应用程序发布,更新代码(例如修复错误、添加新功能)或图像资源,则需要您重新编译和重新分发整个二进制文件,这当然包括您发布到商店时关联的任何审查时间。
CodePush 插件通过保持您的代码和图像与您发布到 CodePush 服务器的更新同步,帮助您立即将产品改进呈现在最终用户面前。这样,您的应用程序获得离线移动体验的优点,以及更新一有可用就侧载的“网络”敏捷性。这是一个双赢!
为了确保您的最终用户始终拥有您应用程序的功能版本,CodePush 插件会保留前一个更新的副本,以便在您意外发布包含崩溃的更新时,可以自动回滚。这样,您可以放心地休息,您的新发布敏捷性不会导致用户在您有机会在服务器上回滚之前被阻止。这是一个赢三次的局面!
解决方案的架构概述 - 您无需担心这一切
什么可以(并将)CodePush
- 您的
/app
文件夹内的任何内容。 - 您的
/node_modules
文件夹内的任何内容。
💁♂️ 注意,我们实际上并没有使用这些文件夹,但在
platforms/ios/<appname>/app
和platforms/android/app/src/main/assets/app
中的app
文件夹中,其好处是我们“不关心”您是否使用 Webpack、Uglify 或您用于压缩或混淆应用程序资源的任何其他工具。
什么不能(将不会)CodePush
- NativeScript 平台更新。例如:将
tns-android
从版本 2.5.1 更新到 2.5.2。 - 需要依赖不同版本的本机库的插件更新。
因此,只要您在 package.json
中不更改依赖项和 tns 平台的版本,您就可以无忧地推送。如果您确实更改了依赖项的版本,请确保没有更改平台库。
入门
全局安装 NativeScript CodePush CLI
npm i -g nativescript-code-push-cli
💁♂️ 这将也将全局
nativescript-code-push
命令添加到您的计算机上。您可以使用nativescript-code-push -v
检查当前安装的版本。
登录或注册服务
检查您是否已登录,以及使用哪个电子邮件地址
nativescript-code-push whoami
如果您已有账户,请登录
nativescript-code-push login
如果您还没有账户,请注册
nativescript-code-push register
这将在浏览器中打开,您可以提供您的凭据,之后您可以创建一个访问密钥,并将其粘贴到控制台。
现在你应该在你的家目录中有一个.nativescript-code-push.config
文件,它将自动使你从这个机器上与服务器进行认证。
请注意,你可以使用该Web界面来管理你的应用,但CLI(命令行界面)功能更强大,因此建议使用命令行界面。
要注销,你可以运行nativescript-code-push logout
,这将删除配置文件。
要执行无头登录(不打开浏览器),你可以这样做:nativescript-code-push login --accessKey <access key>
。
将你的应用与服务注册
为你要针对的每个平台创建一个应用。这样,你可以为iOS和Android分别推出更新。
⚠️
appname
必须唯一,且不应包含连字符(-
)。
nativescript-code-push app add <appname> <platform>
# examples:
nativescript-code-push app add MyAppIOS ios
nativescript-code-push app add MyAppAndroid android
💁♂️ 这将显示你连接到CodePush服务器所需的部署密钥。如果你想在任何时候列出这些密钥,请使用
nativescript-code-push deployment ls <appName> --displayKeys
。
💁♂️ 所有新应用都自动附带两个部署(
Staging
和Production
),这样你就可以开始向多个渠道分发更新。如果你需要更多渠道/部署,只需运行:nativescript-code-push deployment add <appName> <deploymentName>
。
💁♂️ 想要重命名你的应用吗?任何时候,使用以下命令:
nativescript-code-push app rename <oldName> <newName>
💁♂️ 想要删除应用吗?任何时候,使用以下命令:
nativescript-code-push app remove <appName>
- 这意味着任何配置为使用它的应用将显然停止接收更新。
列出你的已注册应用
nativescript-code-push app ls
将此插件添加到你的应用
tns plugin add nativescript-code-push
⚠️ 如果你在你的应用中限制了互联网访问,请确保将我们的CodePush服务器(
https://nativescript-codepush-server.herokuapp.com
)和文件服务器(https://s3.eu-west-1.amazonaws.com
)列入白名单。
检查更新
在安装并配置了CodePush插件之后,剩下的事情就是将必要的代码添加到你的应用中,以控制何时检查更新。
如果有更新可用,它将静默下载并安装。
然后根据提供的InstallMode
,插件将等待下一次冷启动(InstallMode.ON_NEXT_RESTART
)、热重启(InstallMode.ON_NEXT_RESUME
)或对用户提示的肯定响应(InstallMode.IMMEDIATE
)。
请注意,苹果不希望你提示用户重新启动你的应用,所以仅在iOS上为Enterprise分发的应用(或通过TestFlight等测试你的应用时)使用InstallMode.IMMEDIATE
。
💁♂️ 查看我们的示例以获取一个可靠的示例。
// import the main plugin classes
import { CodePush } from "nativescript-code-push";
// and at some point in your app:
CodePush.sync({
deploymentKey: "your-deployment-key" // note that this key depends on the platform you're running on (see the example below)
});
有一些你可以配置的东西 - 这个TypeScript示例具有所有可能选项
import { CodePush, InstallMode, SyncStatus } from "nativescript-code-push";
import { isIOS } from "tns-core-modules/platform";
CodePush.sync({
deploymentKey: isIOS ? "your-ios-deployment-key" : "your-android-deployment-key",
installMode: InstallMode.ON_NEXT_RESTART, // this is the default install mode; the app updates upon the next cold boot (unless the --mandatory flag was specified while pushing the update)
mandatoryInstallMode: isIOS ? InstallMode.ON_NEXT_RESUME : InstallMode.IMMEDIATE, // the default is InstallMode.ON_NEXT_RESUME which doesn't bother the user as long as the app is in the foreground. InstallMode.IMMEDIATE shows an installation prompt. Don't use that for iOS AppStore distributions because Apple doesn't want you to, but if you have an Enterprise-distributed app, go right ahead!
updateDialog: { // only used for InstallMode.IMMEDIATE
updateTitle: "Please restart the app", // an optional title shown in the update dialog
optionalUpdateMessage: "Optional update msg", // a message shown for non-"--mandatory" releases
mandatoryUpdateMessage: "Mandatory update msg", // a message shown for "--mandatory" releases
optionalIgnoreButtonLabel: "Later", // if a user wants to continue their session, the update will be installed on next resume
mandatoryContinueButtonLabel: isIOS ? "Exit now" : "Restart now", // On Android we can kill and restart the app, but on iOS that's not possible so the user has to manually restart it. That's why we provide a different label in this example.
appendReleaseDescription: true // appends the description you (optionally) provided when releasing a new version to CodePush
}
}, (syncStatus: SyncStatus): void => {
console.log("CodePush syncStatus: " + syncStatus);
if (syncStatus === SyncStatus.UP_TO_DATE) {
console.log("CodePush: no pending updates; you're running the latest version!");
} else if (syncStatus === SyncStatus.UPDATE_INSTALLED) {
console.log("CodePush: update installed - it will be activated upon next cold boot");
}
});
点击这里查看JavaScript示例
var CodePush = require("nativescript-code-push").CodePush;
var InstallMode = require("nativescript-code-push").InstallMode;
var SyncStatus = require("nativescript-code-push").SyncStatus;
var platform = require("tns-core-modules/platform");
CodePush.sync({
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 // appends the description you (optionally) provided when releasing a new version to CodePush
}
}, function (syncStatus) {
if (syncStatus === SyncStatus.UP_TO_DATE) {
console.log("CodePush: no pending updates; you're running the latest version!");
} else if (syncStatus === SyncStatus.UPDATE_INSTALLED) {
console.log("CodePush: update installed - it will be activated upon next cold boot");
}
});
何时运行此检查?
建议在冷启动周期中多次检查更新,因此最好将此检查与resume
事件(通常在应用启动时运行)相关联
import * as application from "tns-core-modules/application";
import { CodePush } from "nativescript-code-push";
// add this in some central place that's executed once in a lifecycle
application.on(application.resumeEvent, () => {
CodePush.sync(...);
});
点击这里查看JavaScript示例
var application = require("tns-core-modules/application");
application.on(application.resumeEvent, function () {
// call the sync function
});
发布更新
一旦你的应用已配置并分发给用户,并且你已经进行了一些代码和/或资源的更改,现在是时候将这些更改立即发布给用户了!
⚠️ 确保首先创建一个发布构建,因此使用你用于应用商店分发的相同命令,但不要将其发送到AppStore。你甚至可以使用Webpack和Uglify你的应用,这对插件来说都是透明的。
💁♂️ 当向CodePush发布更新时,你不需要提高应用的版本,因为你根本没有修改应用商店的版本。CodePush将自动为每个发布的发布生成一个“标签”(例如
v3
),以便帮助你在发布历史中识别它。
最简单的方式是使用我们的CodePush CLI中的release
命令。它(最相关的)选项有
参数 | 别名 | 默认值 | 描述 |
---|---|---|---|
部署名称 | d | "测试版" | 部署到"测试版"或"生产版"。 |
描述 | des | 未设置 | 描述使用此版本发布对应用进行的更改。 |
targetBinaryVersion | t | App_Resources |
Semver表达式,指定此版本针对的二进制应用版本(例如1.1.0,~1.2.3)。默认值是App_Resources/iOS/Info.plist 或App_Resources/Android/AndroidManifest.xml 中的精确版本。 |
强制 | m | 未设置 | 此指定更新是否应被视为“紧急”的(例如,它包括关键的漏洞修复)。此属性简单地回传给客户端,客户端可以决定是否以及如何强制执行它。如果未设置此标志,则更新被视为“非紧急”,因此您可以等待应用的下一次冷启动。 |
以下为两个平台提供了一些示例
iOS
nativescript-code-push release <codepush-ios-appname> ios # deploy to Staging
nativescript-code-push release <codepush-ios-appname> ios --d Production # deploy to Production (default: Staging)
nativescript-code-push release <codepush-ios-appname> ios --targetBinaryVersion ~1.0.0 # release to users running any 1.x version (default: the exact version in Info.plist)
nativescript-code-push release <codepush-ios-appname> ios --mandatory --description "My mandatory iOS version" # a release for iOS that needs to be applied ASAP.
Android
nativescript-code-push release <codepush-android-appname> android # deploy to Staging
nativescript-code-push release <codepush-android-appname> android --d Production # deploy to Production (default: Staging)
nativescript-code-push release <codepush-android-appname> android --targetBinaryVersion ~1.0.0 # release to users running any 1.x version (default: the exact version in AndroidManifest.xml)
点击此处了解更多关于--targetBinaryVersion参数的信息
`targetBinaryVersion`指定您要发布更新的应用的商店/二进制版本,这样只有运行该版本的用户才会接收到更新,而运行较旧版本或较新版本的应用二进制文件的用户则不会。以下是一些原因-
如果用户正在运行较旧的二进制版本,那么CodePush更新中可能存在不与他们的运行版本兼容的破坏性更改。
-
如果用户正在运行较新的二进制版本,那么假设他们运行的是较新的(可能不兼容)CodePush更新。
如果您想针对应用商店二进制文件的多版本进行更新,我们还允许您将参数指定为semver范围表达式。这样,任何运行满足范围表达式的二进制版本(即semver.satisfies(version, range)
返回true
)的客户端设备都将获得更新。以下是一些有效的semver范围表达式的示例
范围表达式 | 谁会获得更新 |
---|---|
1.2.3 |
仅运行您的应用特定二进制应用商店版本1.2.3 的设备 |
* |
任何配置为从您的CodePush应用接收更新的设备 |
1.2.x |
运行主要版本1、次要版本2以及任何补丁版本的您的应用的设备 |
1.2.3 - 1.2.7 |
运行任何在1.2.3 (包含)到1.2.7 (包含)之间的二进制版本的设备 |
>=1.2.3 <1.2.7 |
运行任何在1.2.3 (包含)到1.2.7 (不包含)之间的二进制版本的设备 |
1.2 |
相当于>=1.2.0 <1.3.0 |
~1.2.3 |
相当于>=1.2.3 <1.3.0 |
^1.2.3 |
相当于>=1.2.3 <2.0.0 |
**注意**:如果您的semver表达式以特殊shell字符或运算符(如>
、^
或** )开头,则如果未用引号括起来,命令可能无法正确执行,因为shell不会为我们CLI进程提供正确的值。因此,在调用release
命令时,最好将targetBinaryVersion
参数用双引号括起来,例如code-push release MyApp-iOS updateContents ">1.2.3"
。
**注意**:如semver规范中定义的,范围仅适用于非预发布版本:https://github.com/npm/node-semver#prerelease-tags。如果您想更新带有预发布标记的版本,则需要写入您想要更新的确切版本(例如1.2.3-beta
)。
以下表格概述了CodePush期望您的更新semver范围满足的版本值,针对每种相应的应用类型
平台 | 应用商店版本来源 |
---|---|
NativeScript (iOS) | CFBundleShortVersionString 键位于 App_Resources/iOS/Info.plist 文件中 |
NativeScript (Android) | android:versionName 键位于 App_Resources/Android/AndroidManifest.xml 文件中 |
注意:如果元数据文件中的应用商店版本缺少补丁版本,例如 2.0
,则将其视为具有补丁版本 0
,即 2.0 -> 2.0.0
。对于等于纯整数的应用商店版本,例如 1
,在这种情况下将视为 1.0.0
。
了解过去发布的洞察
以下是一些可能对您有用的 CodePush CLI 命令
我创建了哪些发布,以及安装指标是什么?
使用这样的命令将告诉您安装了更新的应用程序数量
nativescript-code-push deployment history <codepush-appname> Staging
产生如下内容
标签 | 发布时间 | 应用版本 | 强制 | 描述 | 安装指标 |
---|---|---|---|---|---|
v2 | 一小时前 | 1.0.0 | 是 | 强制 iOS 版本! | 活跃:11%(19个中的2个) |
总数:2 | |||||
v1 | 2小时前 | 1.0.0 | 否 | 出色的 iOS 版本! | 活跃:26%(19个中的5个) |
总数:5 |
给我当前发布的详细信息!
这将转储应用程序的测试环境和生产环境中最新的发布详情
nativescript-code-push deployment ls <codepush-appname>
如果您还想转储部署密钥,请使用
nativescript-code-push deployment ls <codepush-appname> --displayKeys
产生如下内容
名称 | 部署密钥 | 更新元数据 | 安装指标 |
---|---|---|---|
生产 | r1DVaLfKjc0Y5d6BzqX4.. | 没有发布更新 | 没有记录安装 |
测试 | YTmVMy0GLCknVu3GVIyn.. | 标签:v5 | 活跃:11%(19个中的2个) |
应用版本:1.0.0 | 总数:2 | ||
强制:是 | |||
发布时间:一小时前 | |||
发布者:[email protected] | |||
描述:强制 iOS 版本! |
清除发布历史
这不会回滚任何发布,但它清理了历史元数据(在这种情况下是测试应用程序的历史元数据)
nativescript-code-push deployment clear <codepush-appname> Staging
高级主题
在开发期间测试 CodePush 包
在使用生产环境之前,您可能想先玩一玩 CodePush(明智之举!)在推送更新并将 sync
命令添加到应用程序后,执行以下步骤
$ tns run <platform>
。在 iOS 设备 上添加--release
标志,以便 LiveSync 不会干扰。- 更新安装后,终止并重新启动应用程序
运行演示应用程序
您还可以通过使用其演示应用程序来玩一玩 CodePush。以下是您需要执行的步骤,以观察应用程序更新
- 注册服务(
nativescript-code-push register
)并将演示应用程序添加到您的帐户(nativescript-code-push app add <appname> <platform> nativescript
) - 一旦应用程序注册,您将在控制台看到其部署密钥,使用它们更新 demo 中的密钥
- 转到 src 并运行
npm run preparedemo
- 这将构建插件并将引用添加到演示应用程序中 - 准备一个用作“更新版本”的应用程序(例如,取消注释其中一个 CODEPUSH 标签并注释 APPSTORE 标签),然后运行
tns build <platform>
- 发布更新(
nativescript-code-push release <appname> <platform>
) - 您可以使用
nativescript-code-push deployment history <appname> Staging
确保它出现在更新列表中 - 准备一个用作“官方发布版本”的应用程序(例如,注释 CODEPUSH 标签并取消注释 APPSTORE 标签),然后运行
tns run <platform>
- 当应用程序在设备上部署时,您应该看到“官方发布版本”以及有关已安装更新的信息
- 关闭应用程序(并从设备最近的应用中移除以确保下一次启动为冷启动)然后再次运行它 - 你现在应该能看到应用程序的“更新版本”
修补更新元数据
发布更新后,可能存在需要修改与更新相关的一个或多个元数据属性的情况(例如,你忘记将关键错误修复标记为强制性的)。
点击此处了解有关修补元数据的详细信息。
你可以通过运行以下命令来更新元数据
nativescript-code-push patch <appName> <deploymentName>
[--label <releaseLabel>]
[--mandatory <isMandatory>]
[--description <description>]
[--targetBinaryVersion <targetBinaryVersion>]
⚠️ 此命令不允许修改发布的实际更新内容。如果你需要响应已识别为损坏的发布,应使用回滚命令立即回滚,然后在必要时,在适当的修复可用时发布带有适当修复的新更新。
除了 appName
和 deploymentName
之外,所有参数都是可选的,因此,你可以使用此命令仅更新单个属性或同时更新所有属性。在未指定任何属性标志的情况下调用 patch
命令将不会执行任何操作。
# Mark the latest production release as mandatory
nativescript-code-push patch MyAppiOS Production -m
# Add a "mina and max binary version" to an existing release
nativescript-code-push patch MyAppiOS Staging -t "1.0.0 - 1.0.5"
更新更新
如果你想轻松地将发布从预发布版升级到生产版,请阅读此内容
一旦你针对特定部署(例如 Staging
)测试了一个更新,并且想将其升级(例如,dev->staging,staging->production),你可以简单地使用以下命令将发布从一个部署复制到另一个部署
nativescript-code-push promote <appName> <sourceDeploymentName> <destDeploymentName>
[--description <description>]
[--label <label>]
[--mandatory]
[--targetBinaryVersion <targetBinaryVersion]
# example
nativescript-code-push promote CodePushDemoIOS Staging Production --description 'Promoted from Staging to Production'
promote
命令将为目标部署创建一个新的发布,其中包含来自源部署最新发布的 精确代码和元数据(描述、强制性及目标二进制版本)。虽然你可以使用 release
命令“手动”将更新从一个环境迁移到另一个环境,但 promote
命令具有以下优点
-
它更快,因为你不需要重新组装要发布的发布资产或记住与源部署的发布相关的描述/应用商店版本。
-
它更少出错,因为推广操作确保你在源部署(例如
Staging
)中已经测试过的确切内容将在目标部署(例如Production
)中生效。
💁♂️ 除非你需要修改代码,否则建议的工作流程是利用自动创建的
Staging
和Production
环境,并将所有发布直接到Staging
,然后在执行适当的测试后,从Staging
到Production
执行推广。
回滚更新
如果你想了解有关回滚的所有信息,请阅读此内容
部署的发布历史是不可变的,因此一旦发布,你无法删除或删除单个更新,除非删除部署的所有发布历史。但是,如果你发布了一个损坏的更新或包含意外功能的更新,可以使用 rollback
命令轻松回滚。
nativescript-code-push rollback <appName> <deploymentName>
#example
nativescript-code-push rollback MyAppiOS Production
这将创建一个新的发布,该发布包含与最新版本之前的版本完全相同的 精确代码和元数据。例如,假设你向你的应用程序发布了以下更新
发布 | 描述 | 强制 |
---|---|---|
v1 | 初始发布! | 是 |
v2 | 添加了新功能 | 否 |
v3 | 错误修复 | 是 |
如果你在部署上运行了 rollback
命令,则会创建一个新的发布(v4
),该发布包含 v2
版本的发布内容。
发布 | 描述 | 强制 |
---|---|---|
v1 | 初始发布! | 是 |
v2 | 添加了新功能 | 否 |
v3 | 错误修复 | 是 |
v4(从 v3 回滚到 v2) | 添加了新功能 | 否 |
已经获取了 v3
的最终用户现在将在应用程序执行更新检查时“退回”到 v2
。此外,仍在运行 v2
的任何用户(因此从未获取过 v3
),不会收到更新,因为他们已经在运行最新版本(这就是为什么我们的更新检查除了发布标签之外还使用包哈希的原因)。
如果你希望将部署回滚到除上一个版本以外的其他版本(例如,v3
-> v2
),你可以指定可选的 --targetRelease
参数
nativescript-code-push rollback MyAppiOS Production --targetRelease v34
⚠️ 此操作将回滚到之前的CodePush版本,而不是AppStore版本(如果有中间版本)。
💁♂️ 回滚操作生成的发布版本将在
部署历史
命令的输出中进行标注,以便更容易识别。
应用协作
正在使用多个开发者共同开发一个应用?点击这里!
如果您将与其他开发者共同使用同一CodePush应用,您可以使用以下命令添加他们作为协作者
nativescript-code-push collaborator add <appName> <collaboratorEmail>
注意:这假设开发者已经使用指定的电子邮件地址在CodePush上注册,因此确保他们在尝试与您共享应用之前已经完成此操作。
一旦添加,所有协作者将立即获得以下关于新共享应用的权限
- 查看应用、其协作者、部署和发布历史。
- 向应用任何部署发布更新。
- 回滚应用任何部署
相反,这意味着应用协作者不能执行以下任何操作
- 重命名或删除应用
- 在应用内部创建、重命名或删除新的部署
- 清除部署的发布历史
- 从应用中添加或删除协作者(尽管开发者可以从他们共享的应用中删除自己作为协作者)。
随着时间的推移,如果有人不再与您共同开发应用,您可以使用以下命令将其从协作者中移除
nativescript-code-push collaborator rm <appName> <collaboratorEmail>
如果您想列出已添加到应用的所有协作者,只需运行以下命令
nativescript-code-push collaborator ls <appName>
在代理后使用CodePush
点击此处了解所有关于代理支持的信息
默认情况下,`login`命令将自动查找系统范围内的代理,通过`HTTPS_PROXY`或`HTTP_PROXY`环境变量指定,并使用它连接到服务器。如果您想禁用此行为,并让CLI建立直接连接,只需在登录时指定`--noProxy`参数nativescript-code-push login --noProxy
如果您想明确指定CLI应使用的代理服务器,而无需依赖系统设置,您可以在登录时传递--proxy
参数
nativescript-code-push login --proxy https://foo.com:3454
一旦登录,任何推断的或指定的代理设置都将与您的用户会话一起持久化。这允许您继续使用CLI而无需重新认证或重新指定您首选的代理。如果您想在任何时候开始或停止使用代理,只需注销,然后使用新设置的登录即可。