Takeaways From Migrating an Ember-Cli iOS App from Cordova to Capacitor
Recently, I replaced Cordova with Capacitor in an iOS application. Cordova was working well for the app’s need for the most part, however the Ember-cli library for Cordova hadn’t been updated in a while, and the dependencies began to conflict with others that had already been upgraded. Unfortunately, contributing to yet another open source project wasn’t an option – for this one, I needed to find a solution that was already built.
Thankfully, there is a relatively up-to-date library integrating Ember-cli and Capacitor, ember-cli-capacitor. Also, there were only a couple modules to migrate within the application, and there was full support for Capacitor in both of the modules required by the app – payment and push notifications. The implementations were straightforward; what wasn’t straightforward was learning the intricacies of Capacitor. I had to spend some time configuring Capacitor in order to get it to work, and I had to hunt for some of the configuration changes I made. My hope is that sharing some of the solutions I found will help save you some time, too.
1. You don’t need to use Ionic when using Capacitor
I see “Ionic + Capacitor” in various places, and before I had the Capacitor app working, I was unsure whether Ionic is needed in order for Capacitor to work. It isn’t. I haven’t used Ionic personally, but it seems like a framework that could potentially be used in conjunction with Capacitor (or another platform) to speed up cross-platform development.
2. By Default, Capacitor Intercepts Third-Party Push Notifications
Dictate.life uses OneSignal to deliver push notifications (Thanks, OneSignal!) After implementing the client library in Capacitor and sending a test notification, I wasn’t receiving anything. After setting up OneSignal’s verbose logging and confirming that the network requests for the notifications were being sent and received, I began to look elsewhere for some sort of conflict or error. I eventually stumbled upon ios.handleApplicationNotifications
config option, a directive which tells Capacitor to not intercept push notifications. Once I set that value to false
, the notifications came through.
3. The Configuration Parameter server
Needs to be Disabled for Production Builds/Deploys
Capacitor configuration allows for a server
parameter, which defines the web server that the Capacitor app will point to. This config parameter is incredibly useful when doing local development, since you can pass the URL of your local frontend server to Capacitor, run npx cap sync
, and then you’ll be able to develop your frontend app in the iOS Simulator. If your frontend app has live reload enabled, Capacitor’s server
parameter allows you to take advantage of that feature, too.
Setting the server
parameter is great for development, but when I went to create my first build for TestFlight, the resulting application presented a white screen. I ended up realizing that I needed to make the config file smarter by omitting the server
parameter when creating a build for TestFlight.
I did this by conditionally adding the server
parameter if a DEV
environment variable was present. Then, I prepended that environment variable to my run command for starting the Capacitor stack. If you’re using the json
variant of the Capacitor config file, you’ll need to switch to either the .js
or .ts
version.
Sample Typescript config file:
import { CapacitorConfig } from "@capacitor/cli";
declare var process: {
env: {
[key: string]: string | undefined;
};
}
const config: CapacitorConfig = {
webDir: "dist"
}
if (process.env.ENV == "dev") {
config["server"] = { url: "http://my.dev.url" };
}
Command for starting Capacitor stack:
ENV=dev ember serve
4. The Default Capacitor App is Named ‘App’ and Needs to be Renamed for Real Builds
The default name App
needs to be renamed to your application’s name if you intend to deploy it to the Apple App Store. Changing the default app name is straightforward, but needs to happen in two places:
1. The Podfile
located in ios/app
:
2. The name in Xcode’s App > TARGETS
:
After renaming, run npx cap sync
to propagate the changes.
Conclusion
This migration was relatively easy. In fact, it was fun! Capacitor seems to be working well – I deployed the app (Dictate.life) to the App Store last week, and apart from a couple issues being fixed, it was hard to even notice that the migration occurred. This is the best case scenario! I hope you have similar luck migrating your app to Capacitor!
updated 10.11.2023
Mobile Application Development, Software Engineering