All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog.
- Migration guides for apps and addons moving from
ember-css-modulesto the standalone packages #338
- Handle
undefined/null/empty string passed toclassNames()runtime helper #335 - Drop unmapped class names in
classNames()instead of passing them through, matching v2 behavior #335
- Remove usage of .original in Ember 5.9+ to fix deprecation warnings.
- Glint types for
{{local-class}}#301 (thanks, @SergeAstapov!)
- Avoid triggering (ember.js#19392)[emberjs/ember.js#19392] when we produce synthetic class
AttrNodes.
This major release of Ember CSS Modules primarily removes support for deprecated patterns and updates our minimum support for other elements of the ecosystem.
Ember CSS Modules is now tested against the following as minimum supported versions:
- Ember 3.24
- Ember CLI 3.24
- Node 12
Older Ember and Node versions may incidentally work, but are no longer officially supported.
While ECM will still work for templates backed by Ember.Component classes, all special handling for such components' implicit root element has been removed, in line with the broader ecosystem shift to template-only and @glimmer/component components. This includes the following removals:
- the
@localClassNamesand@localClassNamedecorators - support for
localClassNamesandlocalClassNameBindingsproperties - the
patchClassicComponentconfiguration flag
Special support for Ember.Component was deprecated in v1.5.0 of ember-css-modules; see the changelog for that release for further advice on migrating to newer Octane-based component APIs.
- You can now pass
patchClassicComponent: falsein your ECM config to opt out of the deprecated monkeypatching ofEmber.Componentthat will be removed entirely in 2.0 (thanks @SergeAstapov!)
- Modules whose path includes the name of the package they're in no longer cause issues when resolving
@valueandcomposes:directives (thanks @eshirley and @maxfierke!)
- ECM's support for binding local class names on the root element of a classic
Ember.Compnent(thelocalClassNamesandlocalClassNameBindingsproperties and the@localClassNameand@localClassNamesdecorators) has been deprecated and will be removed in the next major release. These APIs rely on reopeningEmber.Component(which is itself now deprecated) and can be replaced by several alternative patterns. See the Upgrade Notes section below for migration suggestions.
For classic @ember/component subclasses, ember-css-modules has had support for binding static and dynamic local class names to the component's root element using either .extend() or decorator syntax:
export default Component.extend({
localClassNames: ['always-present'],
localClassNameBindings: ['flipACoin'],
flipACoin: computed(function() {
return Math.random() > 0.5 ? 'yes-class' : 'no-class';
}),
});@localClassNames('always-present')
export default class MyComponent extends Component {
@localClassName flipACoin = Math.random() > 0.5 ? 'yes-class' : 'no-class';
}Both versions of these APIs are now deprecated, as:
- they rely on monkey-patching
Ember.Component, which is itself now deprecated - they're parallels of the
classNamesandclassNameBindingsAPIs that are no longer relevant in modern Ember applications
Depending on your appetite for refactoring and modernizing, you might take one of three approaches to migrating off of these APIs:
- Convert your components to use the modern
@glimmer/componentbase class instead of@ember/component. Since Glimmer component templates have "outer HTML" semantics, there's no implicit root element for these APIs to apply to. See the Octane vs Classic cheat sheet for further details on the differences between classic and Glimmer components. - Use
tagName: ''to remove the implicit root element from your classic component, then add a corresponding explicit root element to your template, where you can uselocal-classas you would for any other element. - Import the class name mapping from your styles module and use that with the classic
classNamesandclassNameBindingsAPIs:import styles from './styles'; export default Component.extend({ classNames: [styles['always-present']], classNameBindings: ['flipACoin'], flipACoin: computed(function() { return Math.random() > 0.5 ? styles['yes-class'] : styles['no-class']; }), });
- We now support a wider range of dependencies that includes PostCSS 8 out of the box. Depending on your package manager, you'll likely see this upgrade take effect automatically when you update ECM, and you may see deprecation warnings for any older PostCSS plugins you're using.
If you're using older PostCSS plugins or an older Node version and wish to continue using PostCSS 7, the appropriate dependency versions are still in range for ECM, and we still run tests against them. The easiest way to lock to those versions locally is likely with resolutions entries, which you can see an example of in test-package/old-app.
"resolutions": {
"ember-css-modules/broccoli-css-modules": "^0.7.0",
"ember-css-modules/broccoli-postcss": "^4.0.3",
"ember-css-modules/postcss": "^7.0.35"
},- Ensure styles from addons that define a custom
moduleNameuse correct import paths (#220; thank you @timlindvall!)
- Ensure addons use the host app's
generateScopedNamefor consistency if they don't have their own configured.
- Ensure
ember-css-modulesis initialized beforeember-cli-htmlbars. This almost always was coincidentally the case already, but ordering constraints from other addons could cause ECM to init later, causinglocal-classin colocated templates not to be processed, as in ember-concurrency-async#4
- Ensure local imports work with CLI 3.12 #197
This is a stable release of the changes included in 1.3.0-beta.1 and -beta.2. Headline additions include support for building in projects using @embroider/concat and for defining styles when writing components in the component/template colocation layout.
- Support for Embroider's
staticHelpersflag. #188
- Timing changes to when ECM calculates its configuration caused some addons that late-defined their options (e.g. in their
included()hook) not to be picked up correctly. This timing has been reverted to match that of ECM stable. #186 - ECM no longer emits a nonsense error message without actionable information when a bad import path is specified for a
@valueorcomposesdirective. #186
- Experimental support for apps built using
@embroider/compat. Note that, until embroider-build/embroider#309 is fixed, CSS changes will likely not show up on rebuilds (though corresponding JS changes will) - Experimental support for components in the Octane "colocation" layout (see the README for details.)
- A new
includeExtensionInModulePathoption that, when set totrue, will include.css(or whatever your configured extension is) in the import path for your modules. Note that the extension is always included in the module name for colocated styles in order not to conflict with the component definition itself.
- Support new template factory format coming in Ember 3.13 #146
- ember-css-modules now works in projects using either stage 1 or stage 2 of the decorators proposal, regardless of whether you're using
@ember-decorators/*,ember-decorators-polyfill, or built-in decorator support viaember-cli-babel>= 7.7 and Ember 3.10.
- ECM's template AST transform no longer prevents ember-cli-babel from performing parallel transpilation.
- ember-css-modules now officially supports being installed in projects running either the 3.x or 5.x series of ember-decorators releases #134
@localClassNamesand@localClassNamenow support projects using either stage 1 or stage 2 of the decorators proposal.
- Resolving
@values and class names from addons no longer fails for addons that aren't dependencies of the root application. #125 - Projects using ember-css-modules with other preprocessors (like ember-cli-sass) should no longer see those preprocessors fully rebuild when unrelated files (like templates) change. #120
- The
@localClassNamedecorator now properly works with getters across various Babel and TypeScript versions. #118
- We're now using
broccoli-postcss@4(which itself usespostcss@7) forpostprocessplugins. This should be a non-breaking change for our usage in this addon. #124
- Elements with both
local-classand...attributesshould no longer lose their local class when an externalclassorlocal-classis passed in. #116
The 1.0 release should largely be a drop-in replacement coming from 0.7.x, but there are a few changes to be aware of:
- Referencing a
local-classin a template that doesn't have a correspondingstylesmodule is now a hard error (before it would silently fail and add no class to the target element). - Using
localClassNamesorlocalClassNameBindingson a component with no template is no longer possible. You can either create an empty template for that component or import the styles module and setclassNamesorclassNameBindingsusing the imported mapping, e.g.classNames: styles['my-local-class'].
- The type declaration for
localClassNamesnow uses the right identifier - The error message when referencing a
local-classin a template with no styles module is now more informative
If you're migrating from 0.7.x, see the release notes for the 1.0 betas below for additional changes and fixes.
- The long awaited
@localClassNamesand@localClassNamedecorators, which work as parallels toember-decorators'@classNamesand@className, are now available.
- Turns out there was one breaking change from the 0.7 series: components must now have a template in order for their
localClassNamesandlocalClassNameBindings(as well as the decorator versions) to resolve. The error message for this scenario has been improved to provide more actionable details.
This release is the first beta for Ember CSS Modules 1.0. There are no known breaking changes since 0.7.10, but as described below, there were a few internal refactorings, so we'll run a beta series before christening the official 1.0 🎉
addPostcssPluginnow accepts multiple arguments (#103)
- The
template-only-glimmer-componentsfeature should no longer conflict with ember-css-modules (#98)
- The majority of the runtime monkeypatching that was present in this addon has been removed in favor of build-time processing. The only remaining runtime code is the
{{local-class}}helper and an extension to theComponentclass to supportlocalClassNamesandlocalClassNameBindings. (#99)
- Support importing styles via
@valueandcomposes:from addons with@scopeed names.
- Ember 3.1 ships with a version of Glimmer that expects AST transforms to use a singular
visitorkey rather than pluralvisitors. So we do that. Big thanks to @luqman for tracking this down. - The internal computed property we set up to support
localClassNameBindingsnow uses Ember'sdefinePropertyfor compatibility with the ES5 getters overhaul.
- Nothing. This was essentially a no-op republish of 0.7.7.
- Prerelease versions of Ember CLI are correctly detected now.
- The plugin system now supports a notion of lint plugins, which will activate for developing addons even when they're in
devDependencies.
- The
local-classtemplate transform should now play nicely with ember-font-awesome's own transforms (thanks @buschtoens!) - The plugin registry no longer explodes when addons with no package keywords are present (thanks @devotox!)
- The ability to use
{{local-class}}to inject classes from other modules is now public and documented (thanks @kellyselden!)
localClassNameBindingsnow works with string values instead of just booleans (thanks @luxferresum!)headerFilesandfooterFileswill now accept file paths with and without extensions- Setup for
localClassNamesandlocalClassNameBindingsnow short circuits to avoid extra work for tagless components (thanks @garno!)
- PostCSS plugins can now be specified to run against the final concatenated output of all modules using the
postprocessarray (thanks @alexlafroscia!)
- During testing,
import 'ember-css-modules/extensions'is no longer required to have styles function correctly in integration tests. - When no styles for a component can be found,
localClassNameBindingsnow silently binds no classes instead of throwing an error.
- Modules to be included at the top or bottom of the concatenated output can now be set via the
headerModulesandfooterModulesconfiguration options. See the module ordering guide for details.
@after-modulehas been deprecated in favor of the newheaderModules/footerModulesconfiguration
- Support for Ember 2.15's new form factor for template AST transforms has been added.
- Styles resolution for components and controllers no longer assumes only a single
:in container keys.
- An initial cut of a plugin system has been implemented, allowing common PostCSS plugin sets, shared configuration, and other bits of reusable code to be packaged up and redistributed. See the README for a few implemented examples.
- The CSS Modules pipeline has been upgraded and now uses PostCSS 6
- Some of the more advanced topics in the README have been broken out into dedicated mini-guides in an effort to keep the main document from being so overwhelming
- Attempting to pull styles from an addon that doesn't exist now provides a useful error message (#65).
- There have been some internal changes to how styles are read from the app/addon trees. This should be a non-breaking change (and fixes a number of oddities, including previous incompatibility with lazy engines), but is enough of a shift to warrant a version bump and a note.
- Attempting to import a nonexistent
@valueorcomposea nonexistent class is now a hard error at build time.
- Support for the deprecated
stylesproperty has been removed.
- The (deprecated) computed
stylesproperty is no longer read-only, to allow for other component APIs that expect something with that name to be passed in. - Avoid repurposing
this.optionsin the addon to support Ember CLI 2.12 (#64)
- Now actually avoid triggering the ember-getowner-polyfill deprecation notice.
- This addon will now run before ember-cli-postcss, enabling cooperative preprocessing as with ember-cli-sass and friends (#58).
- Upgraded ember-getowner-polyfill and eliminated a deprecation warning from its changed usage.
- Null local class values, e.g.
local-class={{if false 'foo'}}no longer result in an exception (#57).
- Removed a spurious warning when specifying a local-class for a component that doesn't yet have styles.
- Mirroring the
local-classattribute, there is now alocal-classhelper that can be used in templates to reference local classnames e.g. when passing them to child components as properties.
- In the past, attempting to import a nonexistent class or value would silently fail. This behavior is now deprecated and will be a hard error in the future.
- Usage of the
stylescomputed property on components and controllers is now deprecated.- In templates, you can replace
{{styles.class-name}}with{{local-class 'class-name'}}. - In JavaScript code, you can import the styles object via a normal ES2015
import. - As a migration stepping stone, you can import the styles object and set it on your component/controller's prototype to mimic the old form factor:
import styles from './styles'; export default Ember.Component.extend({ styles, // ... });
- In templates, you can replace
- Support for Ember 1.13 has been removed; ember-css-modules now supports Ember 2.0+.
- Source maps can now be generated for applications, with caveats. See the README and ember-cli/broccoli-concat#58 for details.
- A warning is now issued for addons that have no
addon/stylesdirectory, since Ember CLI won't invoke registered CSS preprocessors in that scenario.
- Fewer files are
required when ember-css-modules loads, lessening the overall impact it should have on Ember CLI's startup time
- Windows is now fully supported (#52).
localClassNameBindingsnow works with classes that usecomposes(#48).
- Virtual modules that export constants can be configured at build time.
- The configured modules extension can now contain a
.(see #41 for history)
- The
local-classattribute now accepts dynamic values (#40) - Components may specify
localClassNamesandlocalClassNameBindings, similar toclassNamesandclassNameBindingsrespectively, to bind local classes to their root elements (#26)
- Values with commas and quotes can now be exposed in modules (#22)
- The beginnings of support for
@valueandcomposes:from addons, with some caveats. Real documentation forthcoming once the feature has a little time to bake.
- Provide caching information for
ember-cli-htmlbarsso it can correctly invalidate when the plugin changes.
- Preliminary support for Glimmer 2 with the Ember alpha series.
- Local class names can be specified via the
local-classattribute (#31) - PostCSS options such as custom syntax are passed through via
postcssOptionsconfig (#34) - The default extension for modules can be specified via
extensionconfig (#34)
- An
intermediateOutputPathmay be specified in order to have ember-css-modules emit to a location other than<app-name>.css, leaving other files in the styles tree untouched for further processing (#28). See the README for further details on how this in combination with the changes in #34 allow for working alongside other CSS preprocessors.
_superis now properly called in the addoninit()to avoid a deprecation notice
0.3.2 Hidden Gems (May 1, 2016)
- Hidden files (e.g.
.DS_Store) no longer break the build process (#21)
- Final linking of
@values now occurs before other PostCSS plugins execute (#23)
- Classes named
containercan be used once again (#15)
- Modules are now more intelligently ordered in the final output by default, according to composition and value dependencies. See the README for further details.
- Ability to override scoped name generation (#3)
- Greater (explicit) control over module ordering in final output (#7)
- Handle component lookup changes in Ember 2.5+ without crashing
- Pass through non-CSS files in the styles tree (#13)
- Don't rely on custom registry options set up in an initializer (#14)