在开发多知之前,我还从来没有正式搞过Web及GUI开发。所以当我的Web版搞得差不多的时候,我知道我可以简单地把它打包成移动应用,但到底用什么就不清楚了。上次了解Hybrid App技术还是在2013年,那时候比较地是PhoneGap和QtQuick。

Google了一下诸如『Package Web App to Native 2019』之类的,历经数次,得出一个结论,我应该用Apache Cordova,which 我从官网上看不出来活跃不活跃,不过Cordova之路我在环境搭建阶段就放弃了,在我根据官方指南,反复地install -g cordova而仍然不能使用cordova cli的时候,我果断地放弃了它。我想,工具链做成这样地框架,质量也好不到哪去。

然后我开始寻找第二个方案,一度甚至想到要用Flutter或React Native重写应用。直到在Ionic4项目里面发现了Capacitor,它的文档堪称典范地短,事实上也很难想象一个为Web App套壳的框架的文档需要像Cordova那么长。

Capacitor是作为Ionic4中Cordova的一个可替换组件而开发的,不过它也在框架设计上(这是自然的)和工具链上支持了为一个现存的项目添加套壳支持:https://capacitor.ionicframework.com/docs/getting-started#adding-capacitor-to-an-existing-web-app

我为iOS和Android套壳的时间分别不超过一天,这还是因为我非常不熟悉移动开发的流程。Capacitor使用在Android上几乎没有任何问题(当然Android工具链本身在Mac上挺有问题)。但是在iOS上有两个重要的问题需要处理。

  1. iOS Status Bar适配的问题(iOS WebView overlay status bar in Hybrid App),iOS上,Capacitor所管理的WebView会占据屏幕的所有空间,所以你的内容会顶到屏幕的上方显示在status bar下面,于是你在iOS App上需要做一点点padding,在Android、Web和iOS PWA、Android PWA上则没有这个问题。我的方案是启动时通过 Capacitor.Plugins.Device查询设备类型,对iOS App类型给body元素设置一个特定的className,在css中对该class设置padding:
// javascript
Device.getInfo().then(res => {
    if (res.platform === 'ios') {
        document.getElementById('root').setAttribute('class', 'iOS-root')
        Capacitor.Plugins.IosSwipeBack.enable()
    }
})

// css
.iOS-root {
    padding-top: 35px;
}
  1. Capacitor iOS App不响应右滑返回事件,需要通过capacitor-plugin-ios-swipe-back来支持,通过Capacitor.Plugins.IosSwipeBack.enable()开启。需要注意的是,该插件在Android项目中会导致构建失败,需要删去,因此在调用上述方法时,需要检测平台支持,以免造成Android App白屏,可以是Capacitor.Plugins.IosSwipeBack && Capacitor.Plugins.IosSwipeBack.enable().

enjoy.

上述两点较为重要,且我查了很久,兹译为英文,以飨非中文读者:
(The above two points are more important, and I have checked it for a long time. I have translated it into English for non-Chinese readers.)

  1. iOS Status Bar in Hybrid App (iOS WebView overlay status bar in Hybrid App), on iOS, the WebView managed by Capacitor will occupy all the space on the screen, so your content will be displayed above the status bar at the top of the screen, so You need to do a little padding on the iOS app. There is no such problem on Android, Web and iOS PWA, Android PWA. My solution is to query the device type through Capacitor.Plugins.Device at startup, set a specific className for the body element for the iOS app type, and set padding for the class in css:
// javascript
Device.getInfo().then(res => {
    if (res.platform === 'ios') {
        document.getElementById('root').setAttribute('class', 'iOS-root')
        Capacitor.Plugins.IosSwipeBack.enable()
    }
})

// css
.iOS-root {
    padding-top: 35px;
}
  1. The Capacitor iOS App does not respond to the right-slip return event and needs to be supported via [capacitor-plugin-ios-swipe-back] (https://www.npmjs.com/package/capacitor-plugin-ios-swipe-back). Capacitor.Plugins.IosSwipeBack.enable() is turned on. It should be noted that the plugin will cause the build to fail in the Android project and need to be deleted. Therefore, when calling the above method, you need to check the platform support, so as not to cause the Android App white screen, which can be Capacitor.Plugins.IosSwipeBack && Capacitor. Plugins.IosSwipeBack.enable().