- Start Date: 2016-07-15
- RFC PR:
- ember-cli Issue:
Make in-repo-addons as self-contained as full addons.
An in-repo addon is a great way to isolate code in an application without
adding the extra costs associated with version management. In some cases,
moving code from app/
to lib/my-addon/
is the first step towards
releasing it as a full, open-source addon.
Unfortunately, there are two important ways in which in-repo addons fail to meet the goal of isolation:
- They cannot declare NPM dependencies
- They cannot declare tests
An in-repo addon has exactly the build-time devDependencies
and runtime
dependencies
as the parent application. This limits the tool's
applicability for use-cases like the following:
- add a dependency e.g., ember-cli-content-security-policy) and configure it
- add a dependency (e.g. ember-tooltips) and some custom CSS for it;
- add a dependency (e.g. ember-modal-dialog) and create a component that simplifies the most
common cases (e.g.
lib/modals/app/my-simple-modal/component.js
) - add a depdency and patch it to fix a bug
The desired behavior is that members of package.json
's ember-addon.paths
are treated like other dependencies. In particular, their dependencies should
end up in node_modules/
. If a dependency is an ember addon,
its app/
and addon/
folders are made available to the application
just as if they had been declared as direct dependencies.
The global npm install
command doesn't know about this logic. Only
and ember-cli command could know about this structure. This RFC proposes
three more-or-less equivalent options:
ember install
with no argumentsember install
with a flag such as--npm
ember npm-install
The command should ensure that the dependencies from the in-repo addons and
the parent app are mutually satisfiable. That is, it should fail if one
in-repo addon declares "ember-foo": "1"
and another "ember-foo": "2"
.
See also ember-cli/ember-cli#5016
In-repo addons aren't ever "installed", which means that they don't automatically run the blueprint with the same name as the addon. However, given
// lib/my-addon/blueprints/my-addon/index.js:
module.exports = {
normalizeEntityName: function() {},
afterInstall: function() {
return this.addBowerPackageToProject('x-button');
}
};
ember g my-addon
does cause the afterInstall
hook to run. This behavior
mimics that of an already-installed external addon.
Adding a test file to lib/my-addon/tests/*-test.js
does not cause it to be
run with the parent app's test suite. Nor is there a way to run just the
tests for one addon.
One major question is how do these tests run?
One option is to simply include them in the tree for the parent app's test suite.
- Pro: existing workflows and scripts will include new tests automatically
- Con: provides less isolation than external addons have
ember test
already has filtering capabilities, so it is possible to run
only the tests from a single addon. It is slightly more difficult to run
only the app's tests -- at least without something like
ember-exam.
A second option is to require each addon to have its own dummy/
app,
just like an external addon.
- Pro: most documentation for external addon development will apply to in-repo addons
- Pro: upgrading an in-repo addon to an external, open-source addon is trivial
- Con: existing workflows and scripts will have to be modified to run all of the app's tests (footgun)
- Con: full test runs will require several build phases, slowing them down
- Con: the
dummy/
apps could get out-of-sync with the main app, making it more difficult to upgrade core libraries likeember
- Con: if two in-repo addons are to each rely on a third, there must
be a way for them to declare that dependency, and ember-cli tools
must understand it. The
npm install
wrapper's logic could become quite complicated.
To run the tests for an in-repo addon, change to the addon's directory
and run ember test
, just like for an external addon.
It may be that some addons are truly specific to the app and are simply a
means of increasing cohesion. The simplicity of the injected approach might
win for these addons. Other addons could be on the path to open-sourcing;
for these, the better parity with external addon structure of the isolated
testing approach might win. It should be possible to support both cases
on a per-in-repo-addon basis, possibly via a flag in index.js
.
If injected tests are easier to make work, support them at first. Over time, if isolated tests are required, allow in-repo addons to opt in to them.
See also ember-cli/ember-cli#4461
- it could slow down the build or rebuild phases
- a dependency that does not appear in
package.json
'sdependencies
will appear in the app, which could further confuse an already confusing dependency-management situation
Unknown
- does an in-repo addon have an
afterInstall
hook? When would it run? - are the tests for in-repo addons injected into the parent app's test suite?