Open-source project
apache/cordova-js avatar
apache/cordova-js

cordova-js: the JavaScript layer every Cordova platform shares

Apache Cordova JavaScript Bridge

642 stars811 forksJavaScriptApache-2.0

At a glance

What is it?
cordova-js is the unified JavaScript layer of the Cordova suite, a Node build tool that bundles the core plugins into a single cordova.<platform>.js file and a small runtime that boots the platform and fires deviceready. It is version 7.0.0-dev, requires Node 22.17 or newer, and it is the piece an implementer extends when adding a platform.
Who is it for?
cordova-js is for people building Cordova applications or adding a platform to the suite, since it is the layer that turns native calls into a single JavaScript bundle and defines the deviceready contract that application code depends on. It is not useful on its own outside a Cordova platform, because the runtime expects a native side that fires onNativeReady.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One runtime, shared by every platform in the suite

cordova-js is described as a unified JavaScript layer for Apache Cordova projects, and the package metadata puts it more precisely: a unified JavaScript layer for the Cordova suite that enables cross-platform native mobile development of applications using HTML, CSS and JavaScript. The reason a shared layer exists is that every Cordova platform needs the same JavaScript runtime, and duplicating that runtime in each platform repository would mean every bug fix and every behaviour change had to be applied many times. Instead there is one repository that owns the runtime, and the platform repositories consume what it produces. The home page is cordova.apache.org, and the code is published on npm as cordova-js with the Apache Software Foundation as the author. The tree is small and legible: src/ holds the runtime source, build-tools/ contains a custom bundler, pkg/ holds the generated platform files, and test/ holds the unit tests, with a Gruntfile.js for the legacy build path, an eslint.config.js for linting, and a karma.conf.js for the browser test run.

The build tool concatenates plugins into one platform file

The mechanism is a Node script rather than a bundler in the usual sense. build-tools/build.js concatenates all of the core Cordova plugins in the repository into a cordova.<platform>.js file under the pkg/ folder, and it wraps the plugins with a RequireJS-compatible module syntax that works in both browser and node environments. The result is a single cordova.js file in which each Cordova plugin is its own module. Two consequences follow. The output is one file per platform, so the webview loads one script rather than a module graph, which is the right shape for a mobile webview that starts on a cold page. And the module format is a compatibility layer rather than a dependency, since the runtime provides its own require implementation under src/scripts/require.js alongside the bootstrap script. The package scripts show the two ways the file is produced: build runs grunt compile, and the test variant is produced by node build-tools/test-build pkg/cordova.test.js. The npm package exposes the build tool as a binary, build-tools/cli.js, which is what a platform repository invokes to produce its own cordova.js.

The channel module is how native code reaches the webview

Event handling in Cordova is a publish and subscribe implementation, and it lives in src/common/channel.js. The project uses it for custom framework events, and it is also the mechanism that starts the whole runtime. The native-to-webview bridge is initialised in src/scripts/bootstrap.js, which attaches the boot function to the channel.onNativeReady event. That event is fired by native code with a single call:

js
  cordova.require('cordova/channel').onNativeReady.fire()

The sequence is short and easy to trace, because it explains why application code waits for deviceready rather than calling an API immediately. The native side has to exist and be ready before any JavaScript can ask it to do something, so the native layer announces itself by firing onNativeReady, and only then does the JavaScript runtime start booting. The channel module is also the general event bus for the framework, so a platform or a plugin can publish and subscribe without touching the bridge directly. The src/common/ directory holds the other shared modules, including argscheck.js for runtime type checking of arguments, base64.js for array buffer conversions, builder.js for installing a set of properties onto an object, utils.js for closures, uuids, object cloning and prototype extension, and exec/proxy.js for adding and removing exec proxy methods.

boot injects globals, then deviceready fires

The boot method does the work, in a deliberate order. It first grabs the common platform definition under src/common/common.js and injects all of the objects defined there onto window and other global namespaces, so that the standard API is available to application code. It then grabs the platform-specific object definitions, as defined under src/<platform>/platform.js, and overrides those onto window, which is how a platform replaces the default behaviour of a shared API with its own implementation. Finally it calls the platform-specific initialize function, located in the platform definition, and at that point Cordova is fully initialized and ready. The last step is to wait for the DOMContentLoaded event so the page has loaded properly, and once that fires Cordova fires deviceready, the event where functions consuming the Cordova APIs can safely be attached. The order is the whole point of the design. Globals exist before deviceready, but the contract with application code is that nothing should call a native-backed API until deviceready has fired, because until then the native side has not confirmed it is listening.

Adding a platform means writing an exec bridge and a definition

The README documents how to create a new platform, and the steps are the clearest description of the plugin contract in the whole repository. In the platform repository, create a cordova-js-src directory. Then write a module that encapsulates the platform exec method and call it exec.js, placed in that directory. The exec method is what enables communication from the platform's JavaScript environment into its native environment, and each platform uses a different mechanism for that bridge. Its signature is fixed, function(success, fail, service, action, args), where success and fail are callbacks, service is a string identifier the platform resolves to a native class, action is a string identifier resolving to a method inside that class, and args is an array of parameters for the native method. New platform additions are required to be as consistent as possible with the existing service and action labels, which is the mechanism that keeps one JavaScript API working across platforms. Then define the platform definition object as platform.js, exporting an id string matching the file name, a bootstrap function that must fire onNativeReady when done, and an optional initialize function called after the global scope setup:

Platform packages build cordova.js through a prepare hook

The fourth step connects a platform repository to this one, and it is the step that makes the whole arrangement work in practice. The modules from cordova-js/src and from the platform's own cordova-js-src directory are bundled into a file that ends up at <platform-project>/platform_www/cordova.js. The recommended way to do that is to add cordova-js as a devDependency with npm i -D cordova-js, and then build cordova.js when preparing the platform's npm package, by adding the npm prepare hook to package.json:

json
      "scripts": {
        "prepare": "cordova-js build > project-template/platform_www/cordova.js",
        // ...
      }

The prepare hook is the interesting choice, because it means the generated file is rebuilt whenever the platform package is packed, so a published platform tarball always contains a cordova.js built from the current cordova-js and the current platform sources, with no separate release step to forget. The hook writes the output through a shell redirect into the platform_www directory, which is where the webview expects to find it. The package metadata for this repository mirrors the same idea in reverse: the version is 7.0.0-dev, the binary points at build-tools/cli.js, and the engines field requires node >=22.17.0.

Tests run in a bundled headless browser, not on a device

The testing section is brief but sets expectations. Tests run in a bundled headless Chromium instance, and the command is npm test, which the scripts show runs the lint step and then karma start. The lint step is eslint with the shared @cordova/eslint-config, and there is an eslint-plugin-es5 dependency in the tree, which reflects that the runtime still has to run on older embedded webviews. The browser side of the test run uses karma with jasmine, a karma-chrome-launcher and puppeteer, so the Chromium instance arrives with the toolchain instead of being assumed on the machine. The final word is in the README's last line on testing: final testing should always be done with the Mobile Spec test application, cordova-mobile-spec, which is a separate repository. That is an honest division of labour. The unit tests here check the JavaScript layer, while the mobile spec is what checks a platform against the full set of plugin behaviours on real platforms. The repository also carries RELEASENOTES.md, a NOTICE file for the Apache licensing, a.asf.yaml file for the foundation's own metadata, and no GitHub releases, with the last push to the repository on 2026-10-22.

Editorial conclusion

cordova-js is for people building Cordova applications or adding a platform to the suite, since it is the layer that turns native calls into a single JavaScript bundle and defines the deviceready contract that application code depends on. It is not useful on its own outside a Cordova platform, because the runtime expects a native side that fires onNativeReady. Before adopting it, check the Node floor of 22.17.0 against the build environment, and remember that the package version in the tree is 7.0.0-dev, so pin a published version rather than tracking the development branch.

Frequently asked questions

What does the cordova-js build tool produce?

The build-tools/build.js Node script concatenates the core Cordova plugins into a cordova.<platform>.js file under the pkg/ folder and wraps them in a RequireJS-compatible module syntax that works in both browser and node environments, giving one file with one module per plugin.

How does Cordova know when the native side is ready?

Native code fires the onNativeReady channel event with cordova.require('cordova/channel').onNativeReady.fire(). The bootstrap script listens for that event and runs boot, which injects the platform objects onto window, calls the platform initialize function, waits for DOMContentLoaded and then fires deviceready.

How do I add support for a new Cordova platform?

Create a cordova-js-src directory in the platform repository, write an exec.js exposing function(success, fail, service, action, args), add a platform.js exporting id, bootstrap and an optional initialize, then bundle both module sets into platform_www/cordova.js through a prepare hook that runs cordova-js build.

What are the Node and test requirements for cordova-js?

The package metadata requires node >=22.17.0. Tests run in a bundled headless Chromium instance with npm test, which lints and then starts karma, and the README notes that final testing should be done with the separate cordova-mobile-spec application.

Official sources

  1. apache/cordova-js on GitHub
  2. Issues
  3. License: Apache-2.0
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/apache-cordova-js.svg)](https://hysenlabs.com/projects/apache-cordova-js)

Was this useful?