Skip to content

Extract module functionality from loading #60

Closed
@geelen

Description

@geelen

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 plugin postcss-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!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions