-
Notifications
You must be signed in to change notification settings - Fork 187
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
Add support for client-side batching to generate fewer <style> tags. #1
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -65,11 +65,55 @@ Support for colocating your styles with your React component. | |
} | ||
}); | ||
|
||
# Buffering | ||
|
||
To avoid making a new style tag for each individual call to `css`, you can use | ||
buffering. A similar technique will enable server rendering. | ||
|
||
On the client, instead of just this: | ||
|
||
ReactDOM.render(<App/>, document.getElementById('root')); | ||
|
||
You can do this: | ||
|
||
StyleSheet.startBuffering(); | ||
ReactDOM.render(<App/>, | ||
document.getElementById('root'), | ||
StyleSheet.flush); | ||
|
||
Note that this is an optimization, and the first option will work just fine. | ||
|
||
Once implemented, server rendering will look roughly like this: | ||
|
||
StyleSheet.clearClassNameCache(); | ||
StyleSheet.startBuffering(); | ||
|
||
// Contains the markup with references to generated class names | ||
var html = ReactDOMServer.renderToString(<App/>); | ||
|
||
// Contains the CSS referenced by the html string above, and the references | ||
// to the classNames generated during the rendering of html above. | ||
var {styleContents, classNames} = StyleSheet.collect(); | ||
|
||
return ` | ||
<html> | ||
<head> | ||
<style>{styleContents}</style> | ||
</head> | ||
<body> | ||
<div id='root'>{html}</div> | ||
<script src="./bundle.js"></script> | ||
<script> | ||
StyleSheet.markInjected({classNames}); | ||
ReactDOM.render(<App/>, document.getElementById('root')); | ||
</script> | ||
</body> | ||
</html> | ||
`; | ||
|
||
# TODO | ||
|
||
- Examples in the repo | ||
- Autoprefixing | ||
- Batch styles in a single render cycle into a single style tag | ||
- Serverside rendering | ||
- Optional AST transformation to replace StyleSheet.create with an object | ||
literal. | ||
|
@@ -80,6 +124,7 @@ Support for colocating your styles with your React component. | |
the unit is. See | ||
[CSSProperty.js](https://github.com/facebook/react/blob/master/src/renderers/dom/shared/CSSProperty.js) | ||
in React. | ||
- Consider removing !important from everything. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 having everything be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I too have felt this pain. |
||
|
||
# Other solutions | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Examples of using inline-styles-that-work | ||
|
||
Run: `npm install && npm run examples`, then open `http://localhost:4114`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<!doctype html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8"> | ||
</head> | ||
<body> | ||
<div id="root"></div> | ||
<script src="./bundle.js"></script> | ||
</body> | ||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"scripts": { | ||
"examples": "webpack-dev-server --content-base . --port 4114" | ||
}, | ||
"author": "", | ||
"license": "ISC", | ||
"devDependencies": { | ||
"babel": "^5.8.23", | ||
"babel-core": "^5.8.25", | ||
"babel-loader": "^5.3.2", | ||
"react": "^0.14.0", | ||
"react-dom": "^0.14.0", | ||
"webpack": "^1.12.2", | ||
"webpack-dev-server": "^1.12.0" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
import ReactDOM from 'react-dom'; | ||
import React, { Component } from 'react'; | ||
import { StyleSheet, css } from '../../src/index.js'; | ||
|
||
const StyleTester = React.createClass({ | ||
getInitialState: function() { | ||
return { | ||
timer: true, | ||
}; | ||
}, | ||
|
||
componentDidMount: function() { | ||
const flipTimer = () => { | ||
this.setState({ | ||
timer: !this.state.timer, | ||
}); | ||
setTimeout(flipTimer, 1000); | ||
}; | ||
|
||
setTimeout(flipTimer, 1000); | ||
}, | ||
|
||
render: function() { | ||
const testCases = [ | ||
<span className={css(styles.red)}>This should be red</span>, | ||
<span className={css(styles.hover)}>This should turn red on hover</span>, | ||
<span className={css(styles.small)}>This should turn red when the browser is less than 600px width</span>, | ||
<span className={css(styles.red, styles.blue)}>This should be blue</span>, | ||
<span className={css(styles.blue, styles.red)}>This should be red</span>, | ||
<span className={css(styles.hover, styles.blue)}>This should be blue but turn red on hover</span>, | ||
<span className={css(styles.small, styles.blue)}>This should be blue but turn red when less than 600px width</span>, | ||
<span className={css(styles.hover, styles.hoverBlue)}>This should turn blue on hover</span>, | ||
<span className={css(styles.small, styles.evenSmaller)}>This should turn red when less than 600px and blue when less than 400px</span>, | ||
<span className={css(styles.smallAndHover)}>This should be red when small, green when hovered, and blue when both.</span>, | ||
<span className={css(styles.smallAndHover, styles.returnOfSmallAndHover)}>This should be blue when small, red when hovered, and green when both.</span>, | ||
<span className={css(styles.red, styles2.red)}>This should be green.</span>, | ||
<span className={css(this.state.timer ? styles.red : styles.blue)}>This should alternate between red and blue every second.</span>, | ||
<a href="javascript: void 0" className={css(styles.pseudoSelectors)}>This should turn red on hover and ???? (blue or red) on active</a>, | ||
]; | ||
|
||
return <div> | ||
{testCases.map((testCase, i) => <div key={i}>{testCase}</div>)} | ||
</div>; | ||
}, | ||
}); | ||
|
||
|
||
const styles = StyleSheet.create({ | ||
red: { | ||
color: "red", | ||
}, | ||
|
||
blue: { | ||
color: "blue", | ||
}, | ||
|
||
hover: { | ||
":hover": { | ||
color: "red", | ||
} | ||
}, | ||
|
||
hoverBlue: { | ||
":hover": { | ||
color: "blue", | ||
} | ||
}, | ||
|
||
small: { | ||
"@media (max-width: 600px)": { | ||
color: "red", | ||
} | ||
}, | ||
|
||
evenSmaller: { | ||
"@media (max-width: 400px)": { | ||
color: "blue", | ||
} | ||
}, | ||
|
||
smallAndHover: { | ||
"@media (max-width: 600px)": { | ||
color: "red", | ||
":hover": { | ||
color: "blue", | ||
} | ||
}, | ||
":hover": { | ||
color: "green", | ||
} | ||
}, | ||
|
||
returnOfSmallAndHover: { | ||
"@media (max-width: 600px)": { | ||
color: "blue", | ||
":hover": { | ||
color: "green", | ||
} | ||
}, | ||
":hover": { | ||
color: "red", | ||
} | ||
}, | ||
|
||
pseudoSelectors: { | ||
":hover": { | ||
color: "red", | ||
}, | ||
":active": { | ||
color: "blue", | ||
} | ||
}, | ||
}); | ||
|
||
const styles2 = StyleSheet.create({ | ||
red: { | ||
color: "green", | ||
}, | ||
}); | ||
|
||
StyleSheet.startBuffering(); | ||
ReactDOM.render(<StyleTester/>, | ||
document.getElementById('root'), | ||
StyleSheet.flush); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
var path = require('path'); | ||
|
||
module.exports = { | ||
entry: [ | ||
'./src/examples' | ||
], | ||
module: { | ||
loaders: [{ | ||
test: /\.js$/, | ||
loaders: ['babel'], | ||
exclude: /node_modules/ | ||
}] | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<script>ReactDOM.render(<App />, document.querySelector("#root"))</script>
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't that strictly worse than
document.getElementById
? Seems like querySelector should just be slower because it needs to the the string parser to figure out to search by id?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like yes: https://jsperf.com/getelementbyid-vs-queryselector
I mostly wanted to mention to add the corresponding client-side
ReactDOM.render
call.