需求背景

  1. ionic项目中没有使用热更新,每次更新内容需要发布新包,因安全扫描、甲方流程等因素,导致不能随意发布版本🚫。即使发布版本用户更新频繁也是不好的体验。
  2. 混合开发模式,在不改变原生代码、插件时,业务代码是具备热更新特性。将不同的业务模块分成单独的服务,嵌入到APP中,使得开发、维护更具灵活性。业务实现不在局限ionic框架,可以使用任意js框架
  3. 采用小程序的思维,可以无限丰富APP功能

技术方案


使用 kunder-cordova-plugin-webview 插件,这个 cordova 插件能够在cordova应用程序中打开第二个 web 视图。此 webview 完全独立于主 webview,但允许你访问插件和其他 Cordova 资源


方案实施


1. Cordova项目安装插件

cordova plugin add https:///kunder-lab/cl.kunder.webview.git

2. 服务端部署cordova.jsplugin 的 js 文件

需要分别部署 android、iOS 平台下的 cordova.js 文件。分别对应的目录为:

ionic实现小程序方案_ionic

ionic实现小程序方案_Android_02


后端部署完成后,拿到 cordova.js的路径,例如:http://xxx/xxx-mobile/assets/android/cordova.js


3. APP打开新的webview

webview.Show(URL);

URL要打开的页面的路径。在 Android 中,URL 前面没有*://javascript:不存在,插件会自动添加前缀,file:///android_asset/www/


关闭第二个 Web 视图并返回主视图,在第二个web视图中调用:

webview.Close();

4. 第三方提供商引入 cordova 能力

在H5项目中引入服务器上的 cordova.js 文件。以vue项目为例,在 App.vue 文件中:

export default {
	mounted(){
		if (process.env.NODE_ENV === "production") {
      // cordova.js 所在的服务器地址
      const host = 'http://xxx/xxx-mobile'
      try {
        let scriptNode = document.createElement("script");
        scriptNode.setAttribute("type", "text/javascript");
        let url = "";
        if (this.$utils.isIOS()) {
          url = host + "/assets/ios/cordova.js";
          scriptNode.setAttribute("src", url);
        } else if (this.$utils.isAndroid()) {
          url = host + "/assets/android/cordova.js";
          scriptNode.setAttribute("src", url);
        }
        if (url) {
          document.body.appendChild(scriptNode);
        }
      } catch (e) {
        console.log(e);
      }
    }
	}
}

插件使用示例,以二维码扫码为例:

// 条形码、二维码扫码
  scan() {
    return new Promise((resolve, reject) => {
      // eslint-disable-next-line no-undef
      barcodeScanner.scan(
        function(result) {
          resolve(result.text);
        },
        function(error) {
          reject(error);
          console.log("Scanning failed: " + error);
        },
        {
          showFlipCameraButton: true, // iOS and Android
          showTorchButton: true, // iOS and Android
          resultDisplayDuration: 1000 // Android, display scanned text for X ms. 0 suppresses it entirely, default 1500
        }
      );
    });
  }