JSPath


前言

  • iOS应用程序上架到AppStore需要等待苹果公司的审核,一般审核时间需要1到2周.虽然程序在上架前会经过测试人员的测试,但有时候还是不免会发生新版本上线后出现严重的bug,导致用户刚升级到新版本就出现crash,严重影响用户体验
  • 这时能做的只是赶紧修复bug然后提交等待漫长的AppStore审核,再盼望用户快点升级,才能完成此次bug的修复,这样及容易导致用户流失,这对企业来说影响非常严重.
  • 为了解决由于AppStore审核而导致程序更新新版本慢,目前有一下2种方案实时修复线上bug:
    • 1.直接使用UIWebView加载网络上的HTML的代码,这样如果有问题只需要更新服务器的HTML文件,用户重新进入程序,加载新的HTML文件,整个程序就能更新.对用户影响非常小
    • 2.使用其他脚本语言通过Runtime动态调用OC
      • 1.WaxPatch:它把Lua脚本语言和原生 Objective-C 应用编程接口(API)结合起来,通过 Lua 脚本来调用OC
      • 2.JSPatch:JSPatch是通过JavaScriptCore.framework调用Runtime,来实现JS调用OC

  • JSPatch优势:
    • 1.JS比Lua在应用开发领域有更广泛的应用,目前前端开发和前端开发有融合的趋势,作为扩展的脚本语言,JS是不二之选
    • 2.JSPatch更符合Apple的规则。iOS Developer Program License Agreement里3.3.2提到不可动态下发可执行代码,但通过苹果JavaScriptCore.framework或WebKit执行的代码除外,JS正是通过JavaScriptCore.framework执行的
    • 3.使用系统内置的JavaScriptCore.framework,无需内嵌脚本引擎,体积小巧
    • 4.支持block
  • JSPatch缺点:
    • 1.相对于WaxPatch,JSPatch劣势在于不支持iOS6,因为需要引入JavaScriptCore.framework
    • 2.另外目前内存的使用上会高于wax,持续改进中
  • 存在风险:JSPatch让脚本语言获得调用所有原生OC方法的能力,不像web前端把能力局限在浏览器,使用上会有一些安全风险
    • 1.若在网络传输过程中下发明文JS,可能会被中间人篡改JS脚本,执行任意方法,盗取APP里的相关信息,危及用户信息和APP
    • 2.若下载完后的JS保存在本地没有加密,在越狱的机器上用户也可以手动替换或篡改脚本
  • 风险控制:

    • 1.JSPatch脚本的执行权限很高,若在传输过程中被中间人篡改,会带来很大的安全问题,为了防止这种情况出现,在传输过程中对JS文件进行了RSA签名加密,流程如下:
      • 服务端: 计算 JS 文件 MD5 值。 用 RSA 私钥对 MD5 值进行加密,与JS文件一起下发给客户端。
      • 客户端: 拿到加密数据,用 RSA 公钥解密出 MD5 值。 本地计算返回的 JS 文件 MD5 值。 对比上述的两个 MD5 值,若相等则校验通过,取 JS 文件保存到本地。
      • 由于 RSA 是非对称加密,在没有私钥的情况下第三方无法加密对应的 MD5 值,也就无法伪造 JS 文件,杜绝了 JS 文件在传输过程被篡改的可能。
    • 2.本地存储
      • 本地存储的脚本被篡改的机会小很多,只在越狱机器上有点风险,对此 JSPatch SDK 在下载完脚本保存到本地时也进行了简单的对称加密,每次读取时解密。
  • JSPatch 需要使用者有一个后台可以下发和管理脚本,并且需要处理传输安全等部署工作,JSPatch 平台帮你做了这些事,提供了脚本后台托管,版本管理,保证传输安全等功能,让你无需搭建一个后台,无需关心部署操作,只需引入一个 SDK 即可立即使用 JSPatch。

  • JSPatch 平台速度和稳定性如何?
    • 通过 JSPatch 平台上传的脚本文件都会保存在七牛云存储上,客户端 APP 只跟七牛服务器通讯,支持高并发,CDN分布全国,速度和稳定性有保证。
  • 除了修复 bug,JSPatch 也可以用于动态运营,实时修改线上 APP 行为,或动态添加功能。JSPatch 详细使用文档见 Github Wiki

JSPatch使用

  • 新建一个OC项目,使用UITableView显示内容:
  • 在显示的数组中故意插入一个元素值为nil.程序立马崩溃
  • 使用JSPatch来动态修改bug

  • 在平台上注册帐号:http://jspatch.com/
  • 新建App:
  • 下载 SDK : 进入:http://jspatch.com/ 点击 SDK下载
  • 下载 SDK 后解压,将 JSPatch.framework 拖入项目中,勾选 "Copy items if needed",并确保 "Add to target" 勾选了相应的 target ,
  • 添加依赖框架:TARGETS -> Build Phases -> Link Binary With Libraries -> + 添加 libz.dylib 和 JavaScriptCore.framework。
  • 添加代码:在 AppDelegate.m 里载入文件,并调用 +startWithAppKey: 方法,参数为第一步获得的 AppKey。接着调用 +sync 方法检查更新

      #import <JSPatch/JSPatch.h>
      - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
          [JSPatch startWithAppKey:@"你的AppKey"];
          [JSPatch sync];
          ...
      }
    
  • 至此 JSPatch 接入完毕,下一步可以开始在后台为这个 App 添加 JS 补丁文件了
  • JSPatch 平台下发 JS 脚本(补丁文件)修复 bug

    • 需要使用JS代码来调用OC代码,必须先熟悉 JSPatch 基础用法, 参见:https://github.com/bang590/JSPatch/wiki/JSPatch-%E5%9F%BA%E7%A1%80%E7%94%A8%E6%B3%95
    • 在 JSPatch 平台的规范里,JS脚本的文件名必须是 main.js

        //main.js
        defineClass("JSPViewController", {
            reloadData: function() {
                require('UIColor')
      
                var array = self.items();
                array.addObject("Patch");
                console.log(array.firstObject());
      
                // 修改talbeView背景颜色和title
                var brownColor = UIColor.brownColor();
                self.tableView().setBackgroundColor(brownColor);
                self.setTitle("使用JSPath防止了崩溃");
            }
        })
      
    • 测试:在上线之前需要对脚本进行本地测试,看看运行是否正常。SDK 提供了方法 + testScriptInBundle 用于发布前的测试:

        #import <JSPatch/JSPatch.h>
        @implementation AppDelegate
        - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
            [JSPatch testScriptInBundle];
            // ...
        }
        @end
      
    • 调用这个方法后,JSPatch 会在当前项目的 bundle 里寻找 main.js 文件执行,效果与最终线上用户下载脚本执行一样,测试完后就可以准备上线这个脚本。
      • 注意 + testScriptInBundle 不能与 + startWithAppKey: 一起调用,+ testScriptInBundle 只用于本地测试,测试完毕后需要去除
    • 效果如下:
    • 在服务器添加添加版本:进入 JSPatch 平台后台,在我的 APP 里选择这个 APP,点击添加版本。填入当前线上 APP 的版本号,可以在项目 TARGETS -> General -> version 上可以找到:, 注意这里版本号必须一致,JSPatch 平台会只针对这个版本号下发对应的 JS 脚本,若版本号对应不上,客户端也就请求不到相应的 JS 脚本。
    • 添加JS脚本: 点击进入刚添加的版本,上传 main.js 即可。
    • 上传完成后,对应版本的 APP 会请求下载这个脚本保存在本地,以后每次启动都会执行这个脚本。至此线上 bug 修复完成。
    • 在AppDelegate里面修改回使用

        - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
            [JSPatch startWithAppKey:@"b338412aba0bd885"];
            [JSPatch sync];
      
        //    [JSPatch testScriptInBundle];
            return YES;
        }
      
    • 修改/删除JS脚本

      • 若后续需要对这个脚本进行修改,可以重新上传新的脚本,APP 客户端会在请求时发现脚本已更新,下载最新脚本覆盖原来的,下次启动时执行。
      • 若想直接取消某个 APP 版本的 JS 脚本补丁,可以直接在 APP 版本界面删除此 APP 版本,APP 客户端会在请求时发现脚本已被删除,即刻删除本地 JS 脚本文件,下次启动时不再加载。

results matching ""

    No results matching ""