-
-
Notifications
You must be signed in to change notification settings - Fork 608
Extract module functionality from loading #60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Nice, and exactly what I'd like to see. I'm currently (after discussion with @markdalgleish over the weekend) aiming to develop a Browserify transform to accommodate CSS Modules. Having |
I already discussed it with @geelen, we are doing this. |
Yes please on the browserify transform, and splitting out the scope part. Share the love 😻 |
please could you bake in the option to disable imports, exports, and extends? i consider those anti-patterns (terrible for code complexity) and would like to prevent those from slipping into our code-base. |
I agree with @necolas. Loader should not became a many-in-one combine. We has many tools to do it. |
+1 for an option to disable imports, exports, and extends |
@ai I disagree, CSS Modules is offering something unique here. AFAIK, CSS Modules are the only way to turn nested |
@necolas (honest question...) do you have a unique class for everything, with styles duplicated between classes? |
@markdalgleish For my concern no. Shared styles are just shared via a component. So no shared styles using extends. |
We've tried to push towards components for everything, but we still share low-level, building-block styles across classes for things like heading text style, since that sort of thing changes between breakpoints and we want our site to work without JavaScript. |
An options to disable import/extends should not be a big deal don't you think ? |
I agree with all of this. I think there is a missunderstanding what CSS Modules are. Here is what they are NOT:
Historically you may have written your components this way: (I assume you are already using local-scoped CSS, as this was not a discussion point) /* buttons.css */
.buttonBase {
border: 1px solid black;
background: #999;
}
.buttonBase:hover {
border: 2px solid black;
background: #eee;
}
.bigButton {
font-size: 200%;
} /* MyComponent.css */
.signInButton {
font-weight: 200%;
} // MyComponent.js
import buttonStyle from "buttons.css";
import style from "MyComponent.css";
// (HTML layout) including this line
<button className={buttonStyle.buttonBase + " " + style.signInButton}>Sign in</button> I interpreted @MoOx comment as he is doing it that way:
If you have two separate roles: developer and designer you could shared the responsibilities in this way:
Ok wait. What if the designer wants to use the - className={buttonStyle.buttonBase + " " + style.signInButton}
+ className={buttonStyle.buttonBase + " " + buttonStyle.bigButton + " " + style.signInButton} Here CSS Modules come into play: All Here the same component using extends: /* buttons.css */
.buttonBase {
border: 1px solid black;
background: #999;
}
.buttonBase:hover {
border: 2px solid black;
background: #eee;
}
.bigButton {
extends: buttonBase;
font-size: 200%;
} /* MyComponent.css */
.signInButton {
extends: buttonBase from "button.css";
font-weight: 200%;
} // MyComponent.js
import style from "MyComponent.css";
// (HTML layout) including this line
<button className={style.signInButton}>Sign in</button> (Four lines where changed: Now everything that concerns the styling is in the CSS file (and in CSS syntax) and layout is in the JS file. Same question: What if the designer wants to use the .signInButton {
- extends: buttonBase from "button.css";
+ extends: bigButton from "button.css"; Technically the resulting CSS and HTML is exactly the same. CSS styles are still shared by including mulitple class names in the HTML I could add a list of benefits, but I don't have time for this, so it's left as an (easy) challenge to the reader. Also take a look at @gaearon's https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0 You propably can apply the same pattern to CSS Modules.
|
@markdalgleish yeap, I mean only about extend and import. But even CSS Modules already exists in separated project ;). |
This is what I am thinking at the moment. Let me know if you have any thoughts about it. What matters to me more than the output from I worked on TweetDeck a few years ago, and at the time it used extends a lot, making the app extremely difficult to work on – and there were only 4 of us working on it at the time. You can easily end up with large, multi-directional inheritance chains and the base classes ossify, since any change to them ripples throughout the app. We chose to rewrite the code to remove the entanglement.
Yes. I assume you're getting at file size concerns. Using components has done a lot to limit the size of our CSS (and JS); I don't think a bit of duplication is a problem in CSS anymore than in JS. Most components don't look the same. And we've encapsulated common sources of unwanted repetition across components into specific, low-level components – Since any feature that is available will find its way into a team's codebase, I'd rather make it impossible for |
I think @necolas is right on the money here. We need to be very careful about separating the opinionated stuff (CSS Modules) away from the generic stuff (the loaders). I'm doing the same with JSPM — a CSS Modules and a raw CSS loader that both share the same core but have very different user-facing functionality. I'm going to put together a low-level spec that I think all the loaders should support unconditionally, since it goes right at the heart of what it means to dynamically load CSS. But it won't include any user-facing syntax, it will just be the glue that allows us CSS Modules people (and anyone else experimenting with CSS syntax) the ability to inform how the loader runs. |
I've just pushed my first crack at a specification of the loader format: https://github.com/css-modules/css-modules/blob/loader-format-documentation/INTERCHANGE_FORMAT.md (discussion in the PR linked above). |
I guess I am still wondering why the approach is to move JS features into CSS rather than move CSS authoring into JS. The local-by-default hack is really useful for pulling in a CSS file (especially existing external packages) and de-globalizing it. That's a cool idea; already started using it. But every time I think about style as a layer in the component – and the sharing of values between the style and other calculations – I end up back at using JS, with CSS being a compile target. With a postcss approach, it's possible to define CSS variables in JS, but then you have to feed those variables into the CSS in the webpack config (to the Doing everything is JS seems to solve the import/export/merge/variables problems more simply, and doesn't prevent the kind of compiled CSS output you get from the current Is there something I'm missing? Would it need a convention like authoring the JS-styles in a separate file and with a specific extension to match against? |
Yeah, I think we're seeing somewhat of a division in gut-feel — I think the future lies in authoring something very CSS-like and consuming it dynamically in JS, you and others appear to go for authoring some or all styles in JS and using CSS as the output. I honestly have no idea which is better, but my gut feel is that authoring in CSS preserves something that authoring in JS lacks, and CSS Modules as a project is about meeting somewhere in the middle. But this issue isn't that one. This issue is about the capability of CSS to be interpreted by the loader and have dynamically-linked symbols, not the correctness in doing so. Without the former, we can't explore the latter. P.S. there's nothing stopping us from allowing JS -> CSS symbol injection. Consider the following: module.exports = { brown: "#700"; } :import("./colors.js") {
__brown: brown;
}
.MyComponent {
color: __brown;
} Obviously, that's the low-level format, so that would be the compile target of some higher-level syntax, probably, maybe something like |
OK. I think there is value in the |
💖 🎉 P A R T Y T I M E S 🎉 💖 |
…l-on-non-latin1-chars Wrap sourceMap JSON in unescape and encodeURIComponent.
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:
Input:
After
parse-imports.js
After
localize-and-extend.js
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:
importLoaders
can be used.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.: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
andextends
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!
The text was updated successfully, but these errors were encountered: