reworkcss / rework-npm

Import CSS from npm modules using rework

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Managing duplicate imports

kristoferjoseph opened this issue · comments

commented

Synopsis

We ran into an issue with having duplicate imports of nested dependencies.
Imagine a button imports a button reset and a button bar imports a button which in turn it imports button reset.
Since imports expand inline to where they are defined the second reset will override the cascade. This is compounded when using this in conjunction with rework-inherit. extend will move selectors in the output so that they no longer remain in the same place in the cascade. You can imagine the numerous issues we have found here.

Proposals

There are many ways we can solve this. What I am looking for here is the preferred way so I can make a pull request.
I'll try to outline the approaches I've come up with. Please comment if there is a better way.

  1. De-duplicate expanded selectors
  2. You could add versions to the expanded selectors in a scope.

De-duplicate is what we are doing now in the name of iteration. This is not going to work in the long run for a couple of reasons.
* There are times when you actually want duplicate selectors
* You could depend on different versions of a nested dependency. i.e. button relies on button reset v1.2 but icon button needed a bug fixed and relies on v1.3. This allows you to lock in blessed versions for a release without needing to update all components.

Expanding seems like the best approach since this would also work for the extend case when used in conjunction with rework-inherit

/* Duplicate selectors for shared code */
.switch:before,
.switch:after {
  position: absolute;
  top: -2px;
}

.switch:before {
  background: blue;
}

.switch:after {
  background: red;
}
commented

What do you think @techwraith @bclinkinbeard

I'm not sure how adding version would work, since the selectors can be anything, such as html or body (which could not be scoped). For example, I'm not sure how to make the following work (if I'm understanding correctly what you're saying for option 2):

Module base:

@import "normalize.css"; // Or whatever reset stylesheet
body {
  font-face: "Helvetica";
}

Module buttons:

@import "normalize.css";
.button { ... }

And then import them:

@import "base";
@import "buttons";

If not deduplicating, this will use the font-face defined in normalize.css, and not the one defined in base, since normalize.css is imported again in buttons. With the current behavior in rework-npm this would work as long as buttons and base do not require conflicting versions of normalize.css and you run npm dedupe.

Definitely not saying that the current behavior is the best; I'm not really satisfied with the way it currently is. The basic problem is that CSS is based on globally defined/modifiable rules and we want multiple versions of these globals.

Also, is option 1 the way it currently works? If I'm understanding you correctly I think it is (only import the same path once in the stylesheet).

commented

I have added a dedupelicate plugin already but as I stated it removes desired selectors as well. I am making it more verbose, but it feels like the wrong approach. The biggest problem as I see it is not being able to respect versioned dependencies.

rework-npm does not import the same file twice in a given scope, but this breaks down when there are nested imports.

Basically extensions need to be handled at a component level before being inserted into the main document.

Any thoughts on how you would like this handled?

Are you interested in me adding the more desired behavior?

I'm not sure that I understand how you are saying to handle it. Can you make an example showing the desired output and how it is different from the current output?

If you want to try to add your desired behavior to rework-npm and make a PR that would be fine. I'm not sure though that I'm understanding what you are trying to accomplish.

Closing this as it hasn't seen any activity lately. Feel free to open a new issue with any input.