There's a number of issues involving assets and how they work in eyeglass with ember apps, especially with ember engines, and especially when those engines are in lazy mode. We're going to change the way assets are configured by default for ember applications so that asset-url() works better and more predictably for ember applications.
Constraints
Current invocations of asset-url() will continue to work unmodified, providing backwards compatibility to existing apps. This change must be non-breaking and introduce no deprecations. The only risk for apps is if there is a url to an asset installed by eyeglass during compilation, where that URL has been hard-coded instead of referencing the asset according to the url returned by asset-url() or asset-uri().
Current Problems:
In some cases, assets installed by eyeglass do not end up in the final build.
Assets in an addon are installed by eyeglass as well as by ember-cli, and depending on configuration, they might be duplicated and have different urls, resulting in additional asset transfer for some applications.
Transitive dependencies on assets delivered by the same eyeglass module in an application can result in the same asset being installed in different locations on a per consuming engine, addon, or application basis.
It's unclear whether relative asset paths are working correctly across the range of use cases for builds occurring in addons and engines.
It's unclear whether assets can be correctly referenced from both the addon and app directories using asset-url().
It's unclear whether assets are correctly handled for nested engines/addons.
Design
Assets delivered from an eyeglass module should be installed to a canonical location. Because eyeglass modules are guaranteed to resolve to a single instance, the assets are guaranteed to be the same across multiple transitive dependencies even if they resolve from npm to different versions.
Asset Installation and Default URLs
Assets will be installed according to the source location.
Assets in the public directory of an application or addon can be referenced by the asset-url() function. Baring intervention from a custom installer, Eyeglass will not install these assets, but it will return a url that conforms to the location that ember will ultimately install the public asset.
Baring intervention from a custom installer, Assets from an eyeglass module will be installed into assets/eyeglass-modules/<module-name>/<path-to-asset>. ember-cli-eyeglass will accept a new configuration parameter that allows the directory of eyeglass module assets to be specified but it will default to assets/eyeglass-modules. The behavior of how conflicts between installed assets and assets in the public directory is handled will be documented, but it is decided by whatever ember-cli does naturally.
An ember engine that is also an eyeglass module can expose assets from a non-public directory. (Open Question: Should addons have this ability without becoming an eyeglass module? The answer may depend on how overrides turn out to work.)
Asset Overrides:
Note: there is currently an override behavior in eyeglass, but it's really not clear how it interacts with ember-cli's public directory semantics We need to decide what the right semantics are and make sure it's clearly documented and implemented accordingly.
Here's how I think it should work:
Assets in the public directory of the app can override the asset normally delivered by an engine, addon, or module by having an asset in a directory that overrides that of the same source url. For example, if an engine or addon named my-swanky-addon has an asset at <addon-root>/public/assets/icons/swanky.gif, then that can be accessed via asset-url("my-swanky-addon/icons/swanky.gif"). If the app puts a different image in the public directory at <app-root>/public/assets/my-swanky-addon/icons/swanky.gif, this will be the asset resolved regardless of whether the app or addon is the one creating the url.
If the asset is referenced as asset-url("icons/swanky.gif") from either the addon or the app, it will still work, but the override location will then be <app-root>/public/assets/icons/swanky.gif and I need to know whether this file would be overwritten by the addon or if the app wins according to ember-cli semantics.
I think the decisions for how to find files in the public directory are based on a merged app tree, not the application source. This means that addons can deliver assets to the app's public directory that have the effect of overriding the assets of other eyeglass addons or modules. This allows for overriding of assets by an addon that nests another addon or is installed along side the main application.
Asset overriding must work the same for both lazy and eager engines, even though lazy engines have a different broccoli tree.
WIP
There's still some unanswered aspects but I want to make sure this core design is solid.
This issue was originally opened by @chriseppstein at https://github.com/sass-eyeglass/ember-cli-eyeglass/issues/52.
There's a number of issues involving assets and how they work in eyeglass with ember apps, especially with ember engines, and especially when those engines are in lazy mode. We're going to change the way assets are configured by default for ember applications so that
asset-url()
works better and more predictably for ember applications.Constraints
Current invocations of
asset-url()
will continue to work unmodified, providing backwards compatibility to existing apps. This change must be non-breaking and introduce no deprecations. The only risk for apps is if there is a url to an asset installed by eyeglass during compilation, where that URL has been hard-coded instead of referencing the asset according to the url returned byasset-url()
orasset-uri()
.Current Problems:
asset-url()
.Design
Assets delivered from an eyeglass module should be installed to a canonical location. Because eyeglass modules are guaranteed to resolve to a single instance, the assets are guaranteed to be the same across multiple transitive dependencies even if they resolve from npm to different versions.
Asset Installation and Default URLs
Assets will be installed according to the source location.
asset-url()
function. Baring intervention from a custom installer, Eyeglass will not install these assets, but it will return a url that conforms to the location that ember will ultimately install the public asset.assets/eyeglass-modules/<module-name>/<path-to-asset>
.ember-cli-eyeglass
will accept a new configuration parameter that allows the directory of eyeglass module assets to be specified but it will default toassets/eyeglass-modules
. The behavior of how conflicts between installed assets and assets in the public directory is handled will be documented, but it is decided by whatever ember-cli does naturally.Asset Overrides:
Note: there is currently an override behavior in eyeglass, but it's really not clear how it interacts with ember-cli's public directory semantics We need to decide what the right semantics are and make sure it's clearly documented and implemented accordingly.
Here's how I think it should work:
Assets in the public directory of the app can override the asset normally delivered by an engine, addon, or module by having an asset in a directory that overrides that of the same source url. For example, if an engine or addon named
my-swanky-addon
has an asset at<addon-root>/public/assets/icons/swanky.gif
, then that can be accessed viaasset-url("my-swanky-addon/icons/swanky.gif")
. If the app puts a different image in the public directory at<app-root>/public/assets/my-swanky-addon/icons/swanky.gif
, this will be the asset resolved regardless of whether the app or addon is the one creating the url.If the asset is referenced as
asset-url("icons/swanky.gif")
from either the addon or the app, it will still work, but the override location will then be<app-root>/public/assets/icons/swanky.gif
and I need to know whether this file would be overwritten by the addon or if the app wins according to ember-cli semantics.I think the decisions for how to find files in the public directory are based on a merged app tree, not the application source. This means that addons can deliver assets to the app's public directory that have the effect of overriding the assets of other eyeglass addons or modules. This allows for overriding of assets by an addon that nests another addon or is installed along side the main application.
Asset overriding must work the same for both lazy and eager engines, even though lazy engines have a different broccoli tree.
WIP
There's still some unanswered aspects but I want to make sure this core design is solid.