Build-time methods for addons to conditionally include functionality based on feature states. These methods are available during the Ember build process and allow addons to adapt their behavior based on optional feature configuration.
Check whether a specific optional feature is enabled, considering both explicit configuration and default values.
/**
* Check if a feature is enabled (explicitly set or using default value)
* @param name - Feature name to check
* @returns true if feature is enabled, false otherwise
*/
isFeatureEnabled(name: string): boolean;Usage Example:
// In an addon's index.js
included() {
let optionalFeatures = this.addons.find(a => a.name === '@ember/optional-features');
if (optionalFeatures.isFeatureEnabled('jquery-integration')) {
// Include jQuery-specific functionality
this.import('vendor/jquery-plugins.js');
}
if (optionalFeatures.isFeatureEnabled('template-only-glimmer-components')) {
// Configure for Glimmer component semantics
this.options.babel = {
plugins: [
// Add Glimmer-specific transformations
]
};
}
}Behavior:
true if feature is explicitly enabled in configurationfalse if feature is explicitly disabled in configurationfalseCheck whether a feature has been explicitly set by the user, regardless of its enabled/disabled state.
/**
* Check if a feature has been explicitly configured by the user
* @param name - Feature name to check
* @returns true if explicitly set, false if using default
*/
isFeatureExplicitlySet(name: string): boolean;Usage Example:
// In an addon's index.js
included() {
let optionalFeatures = this.addons.find(a => a.name === '@ember/optional-features');
if (optionalFeatures.isFeatureExplicitlySet('jquery-integration')) {
// User has made an explicit choice about jQuery
if (optionalFeatures.isFeatureEnabled('jquery-integration')) {
console.log('User explicitly enabled jQuery integration');
} else {
console.log('User explicitly disabled jQuery integration');
}
} else {
// Using default value - perhaps show a deprecation warning
console.warn('jQuery integration will change defaults in future versions');
}
}Behavior:
true if feature is present in config/optional-features.jsontrue if feature is set via EMBER_OPTIONAL_FEATURES environment variablefalse if feature is using its default valueGenerate the EmberENV configuration object based on enabled features.
/**
* Generate EmberENV configuration for enabled features
* @returns Configuration object with feature flags
*/
config(): { EmberENV: Record<string, any> };Usage Example:
// In an addon's index.js
config(environment, appConfig) {
let optionalFeatures = this.addons.find(a => a.name === '@ember/optional-features');
let featureConfig = optionalFeatures.config();
// Merge feature configuration into app config
return {
...featureConfig,
// Other configuration options
};
}Generated Configuration Format:
The configuration object contains EmberENV flags with feature names converted to uppercase constants:
// Example output for enabled features
{
EmberENV: {
_TEMPLATE_ONLY_GLIMMER_COMPONENTS: true,
_JQUERY_INTEGRATION: false,
_APPLICATION_TEMPLATE_WRAPPER: true
}
}Feature Name Transformation:
template-only-glimmer-components → TEMPLATE_ONLY_GLIMMER_COMPONENTS- → _TEMPLATE_ONLY_GLIMMER_COMPONENTS → _TEMPLATE_ONLY_GLIMMER_COMPONENTSFind the @ember/optional-features addon instance within your addon's included hook:
// Standard pattern for finding the addon
included() {
let optionalFeatures = this.addons.find(a => a.name === '@ember/optional-features');
if (!optionalFeatures) {
// Handle case where @ember/optional-features is not installed
console.warn('@ember/optional-features not found, using defaults');
return;
}
// Use optionalFeatures methods...
}Include different assets based on feature states:
included() {
let optionalFeatures = this.addons.find(a => a.name === '@ember/optional-features');
// Conditionally import jQuery plugins
if (optionalFeatures.isFeatureEnabled('jquery-integration')) {
this.import('vendor/jquery-dependent-plugin.js');
} else {
this.import('vendor/vanilla-js-alternative.js');
}
}Modify build configuration based on features:
included() {
let optionalFeatures = this.addons.find(a => a.name === '@ember/optional-features');
if (optionalFeatures.isFeatureEnabled('template-only-glimmer-components')) {
// Configure Babel for Glimmer components
this.options.babel = this.options.babel || {};
this.options.babel.plugins = this.options.babel.plugins || [];
this.options.babel.plugins.push('glimmer-component-transform');
}
}Build-time integration methods are designed to be safe and handle edge cases gracefully:
false for isFeatureEnabled()