callstack / callstack/linaria

Remove evaluation of styled wrapped component

Open
#601 0 comments 1 reaction 0 assignees View on GitHub
enhancement: proposal 💬 skip autolabeling
Dominant language
TypeScript
Stars
12.4k
Forks
413
PR merge metrics
No merged PRs in 30d

Description

## Describe the enhancement

## Motivation

There are some issues caused by evaluating the styled wrapped component.
```js
import {Link} from 'routing-library'
const styled = myLink = styled(Link)``
```
See https://github.com/silvenon/gatsby-plugin-linaria/issues/19 or https://github.com/callstack/linaria/issues/447

It happens because we treat `Link` as a lazy dependency, that has to be evaluated.
We need to evaluate Link, to get it's generated className (in case it will be a linaria styled component).
We want to later produce more specific class names if styled components are composed together. For example given components
```js
// produces selector: '.a'
const A = styled.div`
background-color: red;
`

// produces selector: '.b.a'
const B = styled(A)`
background-color: green;
`

// produces selector: '.c.b.a'
const C = styled(B)`
background-color: blue;
`
```
it generates the following CSS

```css
.a {
background-color: red;
}
.b.a {
background-color: green;
}
.c.b.a {
background-color: blue;
}

```

Which eventually prevents from situation, where rules in CSS are saved in different order than we produced them.
If we skip mentioned evaluation and will not have information about classNames from previous components, it will produce selectors with just class names
```js
const A = styled.div`` // produces selector: '.a'
const B = styled(A)`` // produces selector: '.b'
const C = styled(B)`` // produces selector: '.c'
```
and will generate following CSS

```css
.a {
background-color: red;
}
.b {
background-color: green;
}
.c {
background-color: blue;
}
```

The actual styled component will have these class names regardless the generated CSS
```js


```
So if order of rules in CSS file will not be changed, it will work the same as more specific selectors.

The only place that we do not control in terms of CSS ordering us custom preprocessors or how CSS files are bundled by the bundler. I think with both cases we are safe, because preprocessor cannot break CSS, it has follow its rules, and bundlers should follow files resolution order the same we use to evaluate reps.

@satya164 suggested, we need to check if style loaders also persist the order.

## Possible implementations

We can remove the following condition
https://github.com/callstack/linaria/blob/fb65ee41bf569baa78affbdb2fb74d6bc8784b60/src/babel/visitors/TaggedTemplateExpression.ts#L224-L232
And code responsible for merging the class names

https://github.com/callstack/linaria/blob/fb65ee41bf569baa78affbdb2fb74d6bc8784b60/src/babel/evaluators/templateProcessor.ts#L205-L211

## Related Issues

https://github.com/silvenon/gatsby-plugin-linaria/issues/19
https://github.com/callstack/linaria/issues/447
https://github.com/callstack/linaria/issues/454
and maybe this https://github.com/callstack/linaria/issues/399
https://github.com/zeit/next.js/issues/7769

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.