By Erik Vold

When switching your add-on development from using the older cfx tool to the new jpm tool, there will be a few issues that you encounter. This post is meant to help guide you through these problems when trying JPM.

Remapping Package.json


Add-on ids need to be one of two types, a GUID, or a string that includes an "@" symbol. The cfx tool however would accept most strings without spaces, and append "@jetpack" to the end when generating an install.rdf. This was a legacy decision that we are making a clean break from, so when switching to jpm you will have to manually add "@jetpack" to your "id" in the package.json file for your add-on if it was generated by cfx. A cfx generated id looks something like "jid1-XBSfJmJJlj9GNA" so this would have to be changed to "jid1-XBSfJmJJlj9GNA@jetpack" in order to match the id used by AMO.


Add-on titles should be specified with the title property in package.json, the fullName key that was used by cfx (and is now deprecated) will no longer work with jpm.

Main Entry Point

With cfx generated add-ons the default entry point was lib/main.js, with jpm the default entry point is index.js, so if you want to continue to use lib/main.js you will have to add "main": "lib/main" to your add-on’s package.json file.

Rediscovering Requirements

Third Party Packages

With cfx there were a number of ways to use third party modules, but there was no package manager, so instead of building our own we decided to support npm, which meant building a new loader in order to support NodeJS’s loader logic and this is now used for add-ons made with jpm by default (work by Jordan Santell).

We also decided to drop the legacy methods of including third party packages, so if you’re using a package that isn’t on npm, then tell them to run npm publish on it, because it will be easier for you to use it.

For example, I’ve moved my addon-pathfinder module bundle to npm here.

This guide is a good one for managing dependencies with npm

Relative Paths

If your add-on used "lib/utils/something.js" from "lib/main.js" like this require("utils/something") then this will need to be changed to require("./utils/something") because of the new loader change mentioned above.

The statement require("utils/something") would cause the new loader to look for a dependency named “utils”. This is no different than how node works.

Statements like require("sdk/timers") will continue to work.

Testing Paths

The old cfx loader would allow a file like test/test-main.js to make a statement like reqire("main") would would load the lib/main.js file, the new loader does not do this, the statement would have to be made relative, so reqire("main") should become reqire("../lib/main"). This is no different than how node works.