Skip to content

Commit

Permalink
compile target
Browse files Browse the repository at this point in the history
  • Loading branch information
kof committed Apr 21, 2020
1 parent 6341427 commit a5b7b6a
Showing 1 changed file with 83 additions and 4 deletions.
87 changes: 83 additions & 4 deletions text/0000-cssom.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ While there are many options for authoring CSS, it is super tiresome to convince

### Goals

- CSS scoping (unique selector)
- High-performance rendering of static styles via CSSOM.
- CSS Rules can be reused across components.
- Components have no additional overhead for styling.
Expand Down Expand Up @@ -57,12 +58,71 @@ That being said using a new prop like `css` is also an option:
render(<button css={buttonStyle}>x</button>);
```

### Babel plugin
### A new primitive

Babel plugin can be optional and can enable advanced features like:
Once style or css prop accepts an object that contains CSS, we are essentially creating a new primitive. This primitive can be passed arround, reused, overriden and React will know what to do with it. This opens a number of new doors in the future.

### Compile target

This new primitive can be targeted by compilers (babel plugins and co.). In the simplest scenario it will work without any compilation steps. With compilation it would be possible to compile for example CSS modules into something that React can take and render.

Example of CSS modules being rendered by the new primitive:

```js
import styles from "./button.css";
render(<button className={styles.button}>Hi</button>);
```

What happens right now with CSS loader:

```js
// button.js
import styles from "./button.css";
render(<button className={styles.button}>Hi</button>);
```

Compiles `button.css` to:

```js
// button.css
const createStyleNode = (id, content) => {
const style = document.createElement("style");
style.id = id;
style.textContent = content;
document.head.appendChild(style);
};

createStyleNode(
"/src/button.css:-css",
".button-some-suffix {\n color: red;\n}"
);
```

Instead, it could compile to something like this:

```js
// button.css
export default {
button: {
css: ".button-some-suffix {\n color: red;\n}",
id: "/src/button.css:-css",
},
};
```

and

```js
// button.js
import styles from "./button.css";
render(<button style={styles.button}>Hi</button>);
```

Optionally many other compiler-based things can be enabled:

- vendor prefixing
- optimizations
- optimizations for compression
- linting
- other preprocessing options e.g. using PostCSS

After babel plugin the call into `css` tag function can be removed and the result of the above example can be compiled to:
Expand All @@ -72,6 +132,25 @@ const buttonStyle = { css: ".css-0 { color: red; }" };
render(<button style={buttonStyle}>x</button>);
```

### Object based styles syntax

It is still possible to use object based syntax like in [JSS](https://github.com/cssinjs/jss/blob/master/docs/jss-syntax.md) or React Native. It is possible because in the end it's still going to be a CSS string which can be passed to React:

```js
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
}); // {container: {css: ".r-d23pfw {flex: 1; justify-content: center; align-items: center;"}}
render(
<View style={styles.container}>
<Text>Hi</Text>
</View>
);
```

# Drawbacks

- we are adding a new area of responsibility to React, which will require more work to maintain it, but hopefully can be parallelized
Expand All @@ -96,7 +175,7 @@ It is a primitive interface for passing CSS to React to integrate with component

# Unresolved questions

- Unique class names generation algorithm
- Specific algorithm for unique class names generation
- Composition
- Overrides
- Dynamic or state-based styling
Expand Down

0 comments on commit a5b7b6a

Please sign in to comment.