Geekits 是我开发了五年多的开源项目,也是我维护最久的开源项目。在经过不断的迭代之后,在 Next 技术栈稳定了下来。
本文将介绍我如何把一个纯 Web App 改造为优雅的原生 App,让这个产品支持多终端运行。
其实改造要做的工作不仅仅是把 App 放入 Webview,而是要移除原生app不需要的功能,用原生 API 替换某些 JS 实现的功能,样式的适配等等。
为什么要做原生 App
我个人并不完全赞同“Web 才是未来”的说法。但我很喜欢 Local first 的 web app,所以即使在开发 Web App 时,我都尽力让 Geekits 离线可用。
而迁移到原生让 local first 的实现更加方便,资源加载更快,大的数据也无需联网加载(例如成语查询功能)。
不仅如此,可操作的窗口尺寸也更大了,不用担心标签页会被不小心关掉,响应速度也更快。
最后,系统提供了更多浏览器不便获取(或者版本受限)的信息,例如加速度传感器,电池信息等。
Step 1 - 安装配置 Capacitor
得益于 Capacitor 不错的 DX,一切顺利的话,你只需要几分钟即可得到一个“能运行的”原生版本。
首先,安装 Capacitor:
修改配置文件 capacitor.config.js :
如果你的 Next APP 一直是纯静态导出,那么恭喜你,大功告成。运行此命令可将你的 Next App 编译为静态文件:
接着将编译出的代码同步到 Capacitor:
大功告成!
但如果你的 Next App 使用了混合构建模式(例如使用了服务端功能),你可能无法直接执行 next export。你需要将一些依赖服务器的逻辑移动到客户端处理。例如:
- 客户端使用 device API 获取 locale(而不是 Next 的 Locale API)
- 客户端使用 hook 获取数据(而不是从 getServerProps 等方法)
从客户端获取 Locale 的示例如下:
Step 2 - 添加屏幕安全区域
至此我们已经拥有一个基本的原生 App,但仍有很多小问题需要适配。
不同于浏览器环境,移动设备异形屏会影响显示,例如刘海和打孔。为了避免出血,可以在全局 CSS 文件加如下全局变量:
然后在需要预留 Bleeding Area 的地方使用该属性,例如 Appbar(头部):
Step 3 - 运行时条件处理
尽管 Capacitor 提供了检测运行平台的 API,但在 Next 静态导出的过程中,其API总是会检测为浏览器环境。
例如,有时候我们希望某些 React 组件仅在原生平台中出现,在导出时就需要告知 Next 我们是否在为原生平台打包。
为了在 Next 导出过程中检测指定打包平台,我们可以手动添加一个环境变量指定导出目标。方便起见,你可以在 package.json 中写入以下脚本:
接着封装一个方法检测打包平台:
Step 4 - 添加原生图标
Capacitor 并不会为你生成各种尺寸的原生 App 图标,你需要自己手动制作替换。
你只需准备一张 1024 * 1024 的图标原图,接着你可以利用这个工具一键生成 iOS 和 Android 平台的图标。
将下载下来的文件替换项目中的文件即可。
P.S. 此工具无法生成 Adaptive Icon,你需要自己制作前景和背景。
后续流程
Capacitor 的功能远不止本文所写,你可以从官方文档探索更多可能。