Hi all,

I just wanted to announce that I've been experimenting with a different way of authoring Cordova plugins. I don't really have anything to show right now, but looking to get some abstract high-level feedback based on the idea.

This is more or less a preliminary start of a discussion so that I can get some early feedback. The plan is to come back some time later with a more official specification document and usable PoCs for both Android & iOS platforms.

Privately I've been experimenting with a more closer "native" method which I feel like solves several issues
with the way that cordova plugins are traditionally authored.

First I'll explain briefly the pains of authoring cordova plugins, and then I'll explain a high level idea that will likely solve the problems.

Currently the plugins are authored by having a set of arbitrary source files as defined by the <source-file> / <header-file> directives, which also declares where these files should be copied to into the cordova native app project. Additionally, if the plugin requires changing resource files or adding additional configurations, they must make use of several directives which may include:

- config-file
- edit-config
- resource-file
- lib-file
- framework
- source-file / header-file
- asset


Most of these works well enough, but shouldn't be necessary to begin with. Others, are very finicky or are barely usable due to bugs or other caveats (e.g. config-file and edit-config)

The second issue with the way that Cordova plugins are traditionally authored (based on the Official Apache plugins) is that they aren't unit testable. They can only really be tested as part of a real cordova project, which we currently do via cordova-paramedic. This is because there is a disconnect between the plugin sources and an actual native project.

So I've been experimenting with authoring cordova plugins using a native project that gets imported a cordova project. Right now my experimentation has been exclusively with the Android platform, so I'll be using more Android-specific examples.

But my experimentation has me building a cordova plugin that instead of containing loose java source files, they contain an actual Gradle project that builds an Android Library. This means that the Cordova Plugin has it's own:

- Source files
- AndroidManifest
- resources
- Gradle configs & dependency management

With these tools at the plugin's author disposal... it should eliminate, or mostly eliminate the need of the aforementioned directives:

- edit-config

Is no longer required to edit AndroidManifest.xml, but may still be required to edit config.xml (but is there really a need to?). Instead native libraries have their own AndroidManifest.xml which will get merged with the App's manifest.

- lib-file

A native library can bundle their own lib-files.

- resource-file

A native library can bundle their own resource files.

- framework

A native library has it's own gradle file to manage frameworks/dependencies

- source-file / header-file

A native library has it's own file structure for their source files, whether java or native C++ modules.

- config-file*

While won't be needed to edit AndroidManifest.xml for the same reason as edit-config, which was a common use case... It will still be required for setting up cordova Feature tags/declarations which gets placed into `config.xml`.

- asset*

Untested, I'm not sure if assets will get merged in a way that is usable by the app. So this directive may still be relevant.

Additionally, the js-module directive will still be relevant as the native project has no concept of setting up the webview JS modules.

*To be clear*, I'm not suggesting that the current plugin.xml directives to be deprecated or removed. They are still going to be required to support any cordova plugin authored in a traditional method. However, with the module method, most of these directives won't be necessary to use. In fact, I think the module method could continue to use any one of the existing directives if they choose to, but in all likeliness, there won't be a need to. In practice we may want to discourage people to use the "legacy" directives so that support could be considered to be dropped in the future.

I foresee a new directive being created to declare the "module" directory, which is the root folder of a native project, which would simply be copied in full to a directory inside the app project. For example, the module format really needs 4 main actions to be done in a cordova android project. I'll pretend that cordova-plugin-file is authored in a module format containing a gradle project.

Cordova will need to:

1. Copy the cordova-plugin-file gradle project into a subdirectory (e.g. /platforms/android/cdvModules/cordova-plugin-file) 2. settings.gradle needs a line to include the gradle project into it's build system (e.g. include ":cdvModules:cordova-plugin-file") 3. The "app" module needs to depend on cordova-plugin-file (e.g: implementation project(":cdvModules:cordova-plugin-file")) 4. Configure the JS-modules / config.xml "Feature" tags just like it always did before.

Apache Cordova will still not be distributing prebuilt libraries (e.g. plugins are not AAR or xcframeworks) but rather the complete module that can be copied into a project as a module. The module itself will contain all the build scripts and source code. I believe this still satisfies Apache's Release policy requiring source packages with no compiled code[1]. Of course, third-party plugin authors can still utilize this method of authoring plugins and still include closed sources or libraries if they choose so.

Lastly, now that the plugin has a native project housed, it will also be much easier to unit test the native side. However there is one caveat where e2e tests cannot be done as that will still require a real cordova project,
so cordova-paramedic will still have to be used for e2e testing.

I do have a working example of this system I described for Android but I still have lots of testing to do myself. Still, I feel very confident that this is major improvements to how plugins are authored, which hopefully will encourage well written and well tested plugins, as well as reducing the need for plugin authors to manipulate the app's resource files, which can often result in conflicts.

Moving forward I'd be continuing to experiment with both the Android & iOS platforms, preparing proof of concept repositories as well as a specification document for a lower level detailed of what implementation may look like, which can then be further reviewed/commented.

Looking forward for any comments, questions, or concerns.

Cheers,
Norman

References:
[1] https://www.apache.org/legal/release-policy.html#source-packages

Reply via email to