Description
Been chatting with @markdalgleish about this, but I thought I'd put my thoughts down into an issue that was a bit more async-friendly (since he has a day job and so chatrooms aren't ideal).
I love the module mode for css-loader, I love the local-by-default idea, as well as being able to import other files & extend classes. But I think those things are being all tied together in the current implementation, and could be broken out, which would mean more flexibility, reuse, and ease-of-contributions.
Here's my suggestion:
- Define a series of PostCSS transform that take the currently-supported syntax and converts it. Taking the example off the home page.
Input:
:local(.continueButton) {
extends: button from "library/button.css";
background: red;
}
After parse-imports.js
:import("library/button.css") {
button: __tmp_487387465fczSDGHSABb;
}
:local(.continueButton) {
extends: __tmp_487387465fczSDGHSABb;
background: red;
}
After localize-and-extend.js
:import("library/button.css") {
button: __tmp_487387465fczSDGHSABb;
}
:export {
continueButton: _13LGdX8RMStbBE9w-t0gZ1 __tmp_487387465fczSDGHSABb;
}
._13LGdX8RMStbBE9w-t0gZ1 {
background: red;
}
These transformations each have a single responsibility, are easier to test & maintain, can operate on a single file at once and totally agnostic to Webpack/JSPM/Browserify. After this:
- Automatically attach those two PostCSS transforms in the same way
importLoaders
can be used. - If
css-loader?module
is set and CSS Module mode is activated, add the pluginpostcss-local-scope
to translate.localName
to:local(.localName)
, just as it was before. - The current localisation/extension logic is adapted to look for the
:import
and:export
primitives, and look for usages of temporary imported symbols (e.g.__tmp_487387465fczSDGHSABb
) and replace them with the exports of another file.
So, this achieves a couple of things. It reduces the complexity of this project in particular, yet still presents the same interface to users of the module (:local
and extends
are always available, local-by-default is there in "module mode"). I can implement :import
and :export
for JSPM, and then we can share the CSS Modules syntax & plugins. I think it increases the chances of making CSS Modules a specification, since we'll have multiple loaders using it (more users) & be able to solve spec-level issues at the same time for everyone.
I'm happy to build these PostCSS plugins, and I think I could write a PR to include them as importLoaders
. Getting :import
and :export
to work might be a bit beyond me right now.
From the reaction to both this project & Mark's blog post last week, as well as the discussions at CampJS and in chat rooms, people are really excited about this kind of functionality. I think this would make a good next logical step for the life of CSS Modules, and give it the best chance of being adopted globally.
Thanks!