DEV Community

Cover image for Develop 99% of your Ionic app in the browser with Capacitor
Max Lynch for Ionic

Posted on • Originally published at ionicframework.com on

Develop 99% of your Ionic app in the browser with Capacitor

One of the very special things about Ionic and Capacitor is that a huge bulk of your app development can happen right in a browser on your desktop. That means full access to your traditional desktop web development tools (Chrome/Safari/Firefox dev tools) and the development velocity of building without having to recompile or deploy to a simulator or device.

One of the guiding design goals of Capacitor, Ionic’s new native web app container project that runs your web app natively on iOS, Android, Electron, and the web as a Progressive Web App, was to increase the amount of time you can spend developing your app on desktop before having to mess with simulators or devices.

On top of that, building web-first means that your app will likely run well as a Progressive Web App with minimal additional work, assuming you’re able to achieve the functionality your app needs with Web APIs.

Let’s take a look at how that works.

A Fake Native Plugin

Chances are, your Ionic/Capacitor app will have some native functionality that it needs, that goes beyond what is available out of the box in Capacitor (such as integrating with a 3rd party SDK).

Let’s say we have this simple Capacitor plugin:

import Foundation
import Capacitor

@objc(ThirdPartyPlugin)
public class ThirdPartyPlugin: CAPPlugin {
  @objc func connect(_ call: CAPPluginCall) {
    let service = ThirdPartySDK(apiKey)
    service.connect()
    call.resolve(service.getUser())
  }
}
Enter fullscreen mode Exit fullscreen mode

This plugin connects to the ThirdPartySDK and then returns some user information. Unfortunately, this theoretical SDK is only available on iOS and Android, so when we’re building the app in the browser, we will need to either add custom code to detect which platform we’re running on (not ideal), or mock out the service so we can keep building quickly (much better!)

Mocking Plugins on the Web

In order to mock out this plugin, we need to create what is known as a Web Plugin for Capacitor. Web Plugins have a lot of power and aren’t just for mocking though! For example, Capacitor ships with a full Filesystem implementation for the web that uses IndexedDB so you can work with files just like on iOS, Android, and Electron.

In this case, our web plugin will be pretty basic and just return some fake data, so let’s create it:

import { WebPlugin } from '@capacitor/core';

export class ThirdPartyPluginWeb extends WebPlugin {
  constructor() {
    // Register the plugin with Capacitor so it is aware of it
    super({
      name: 'ThirdPartyPlugin',
      platforms: ['web']
    });
  }

  async connect(options: any) {
    return {
      id: 123,
      name: 'Barnaby Jones',
      email: 'barnaby@aol.com'
    }
  }
}

export const ThirdPartyPlugin = new ThirdPartyPluginWeb();
Enter fullscreen mode Exit fullscreen mode

Next, we need to register this plugin with Capacitor so it is aware of it. This makes your plugin available at runtime, but only when running on the platforms specified in the constructor (in this case, web):

import { ThirdPartyPlugin } from './plugins';
import { registerWebPlugin } from '@capacitor/core';
registerWebPlugin(ThirdPartyPlugin);
Enter fullscreen mode Exit fullscreen mode

Where you put this code does matter, to ensure it loads before this plugin is accessed, so we recommend putting it in your root index JS/TS file.

Testing the Plugin

Once you have your plugin built, using it is as simple as just serving your app normally (npm start, for example), and then invoking the plugin like so:

import { Plugins } from '@capacitor/core';

function connectToThirdParty() {
  const { ThirdPartyPlugin } = Plugins;

  const user = await ThirdPartyPlugin.connect();
}
Enter fullscreen mode Exit fullscreen mode

You should see your mock web data come back when running on the web, otherwise see the normal full connection to the Third Party SDK when running natively!

If you’re having trouble, try accessing your plugin on Plugins as close to where it is used. Unfortunately, with modern bundlers and module loaders, your code may be referencing Plugins.ThirdPartyPlugin before the web plugin has loaded, so be mindful of that.

Conclusion

Web Plugins are wonderful for building out consistent cross-platform APIs (for example, the Geolocation and Share APIs have the same code on all platforms), but they can also be used for mocking out functionality that is only used on native platforms.

If you end up building a web plugin for Capacitor and find this guide helpful, let us know below!

Top comments (3)

Collapse
 
jingzhou profile image
jing-zhou

Is there a process for migration from Cordova to Capacitor?

Collapse
 
dotnetkow profile image
Matt Netkow

Yes! Start here in the Capacitor docs.

Collapse
 
atilacamurca profile image
Átila Camurça Alves

Any plans to create official mocks for the most common plugins?