-
Notifications
You must be signed in to change notification settings - Fork 263
JEP Packageless
This page describes how module system will work in the future versions of add-on sdk.
- Packages seem to be too heavy weight.
- Packages require tools like package managers to be useful.
- Packages require central repositories for publishing.
- Package identifiers / names may conflict and there for require implementing a conflict resolutions.
- Modules are light & encourage minimalism.
- Modules don't necessary require tools to be useful. ES.next uses URLs to code as an identifiers.
- Modules don't need additional central repository, simple registries may be build to ease discovery of popular module URLs.
- Modules are similar to script tags and that's what we have on the web today and what we'll have in a future
Add-on is just a directory with a package descriptor and an entry point module. In a common case it has a following layout:
${ADDON}/package.json
./main.js
./icon.png
./test/all.js
Module may declare dependencies on other modules via
require
statements. Add-on sdk recognizes several types
of dependencies:
Idiomatic add-on code is authored in multiple modules
that do one thing at a time. Some of these modules may
be located near each other. Modules that can be referenced
via relative path are considered local. All local
module requirements IDs start with character .
require('./toolbar')
require('./toolbar/view')
require('../../outside/of/addon')
Code that is generic enough, to be useful outside of specific add-on, is better be shared with others. Such modules (typically third party libraries) may be placed in a specific location to be requireable. These modules can be required by a non relative require form.
require('fs')
require('streamer')
require('backbone/model')
Following requirement usually translates to:
require('./@modules/fs')
require('./@modules/fs')
require('./@modules/backbone/model')
If requirements are not discovered under appropriate paths they will be searched one level up:
require('../@modules/fs')
require('../@modules/fs')
require('../@modules/backbone/model')
Goin upwards until add-on root is reached.
Note: special @modules
folder is exact equivalent of
nodejs's node_modules
and we may decide to go with a
different name instead.
Modules that have external require form and are not
discovered are considered system. Such modules are
found either in the lib
directory of the add-on sdk or
are shipped with a platform itself. These modules have
following forms:
require('panel')
require('tabs')
require('sdk/window/events')
require('devtools/scratchpad')
Single term system modules (ones that do not contain
/
character) are just high level SDK modules and represent
just a convenience shortcuts for multi-term equivalents:
require('sdk/panel') // panel -> sdk/panel
require('sdk/tabs') // tabs -> sdk/tabs
require('sdk/window/events')
require('devtools/scratchpad')
Also system module require form represents just a convenience
form for loading modules relative to loader's baseURI
. For
add-on sdk add-ons it's equivalent of:
require('resource:///modules/sdk/panel.js')
require('resource:///modules/sdk/tabs.js')
require('resource:///modules/sdk/window/events.js')
require('resource:///modules/devtools/scratchpad.js')
Note: Unlike in nodejs, remote modules take precedence over system ones. This is intentional as new system add-ons may be added after add-on is installed, shadowing modules that add-on had dependency upon, would break it when users update application.
Different tools may be build / used to help users organize dependencies. SDK will come with a built-in tool to make dependency management transparent for users. SDK will recognize distinct external require flavors to achieve that:
External dependencies that have form of http / https URLs
(excluding http://
and https://
) will be recognized and
installed at build time to make them available at run-time:
require('git.io/streamer')
require('raw.github.com/gist/1733262/d98dd3f854eed5deb129122e2459de10a5e609a0/recovery')
Note: Modules from associated URLs will be downloaded
and to @modules
directory at build time, so no fetch from
remote servers will happen at run-time. This is somewhat
equivalent of JS files in HTML app-cache manifest with a
difference that SDK will download and update app-cache
automatically for users.
Remote modules written for third party consumption may also depend on assets different from modules. Such dependencies may be declared via special require form that SDK will also be recognized by SDK and will be bundled with an add-on.
var iconURI = require('asset!./icon.png')
Note: Each asset will have to be declared as SDK won't parse html or alike to figure out non declared dependencies.
Most of this changes are backwards compatible. While it may
break some exotic require forms (like require('utils')
meaning require('./utils')
) it's still pretty trivial to
fix those and we may even build tools to help migration.
While add-on sdk will come with a built-in tool that we believe will be a best match for most add-ons, we recognize it may not match all cases. There for we build infrastructure first that would allow users to write / choose alternative tools (npm comes in mind).