Function createMuiTheme() created the font families with escaped \" characters:
fontFamily: "\"Roboto\", \"Helvetica\", \"Arial\", sans-serif"which is converted to"by JSS functionSheetsRegistry.toString()instead of ", and this style will be ignore during initial render by browser causing the font to flip.
createMuiTheme(): fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif'
// or
fontFamily: "'Roboto', 'Helvetica', 'Arial', sans-serif"
index.html <style id="jss-server-side">html {
...
.jss49 {
....
font-family: "Roboto", "Helvetica", "Arial", sans-serif;
}
createMuiTheme(): fontFamily: "\"Roboto\", \"Helvetica\", \"Arial\", sans-serif"
index.html <style id="jss-server-side">html {
...
.jss49 {
....
font-family: "Roboto", "Helvetica", "Arial", sans-serif;
}
This style will be ignored by the browser and replaced when the hydration completed with the correct font, causing the screen to flip.
Please run createMuiTheme() and observe the result.
I suggest this is a bug because material-ui decision to use JSS should mean it should provide what JSS need to work.
SSR rendering part renderToHtml: (render, Comp, meta) => {
const sheetsRegistry = new SheetsRegistry()
const sheetsManager = new Map()
const theme = createMuiTheme() // <-- this is the problem
\\ the font families were created with escaped quote characters:
\\ `fontFamily: "\"Roboto\", \"Helvetica\", \"Arial\", sans-serif"`
const generateClassName = createGenerateClassName()
const html = render(
<JssProvider registry={sheetsRegistry} generateClassName={generateClassName}>
<MuiThemeProvider theme={theme} sheetsManager={sheetsManager}>
<Comp />
</MuiThemeProvider>
</JssProvider>
)
meta.jssStyles = sheetsRegistry.toString() // <-- this will convert escaped quote characters \" to " instead of "
return html
},
-->
Link: N/A
initial font rendered by the client is incorrect, causing the screen to flip.
| Tech | Version |
|--------------|---------|
| Material-UI | v3.1.0 |
| React | 16.5.1 |
| Browser | Google Chrome v69.0.3497.100 (64-bit) |
| TypeScript | N/A |
| etc. | |
馃憢 Thanks for using Material-UI!
We use the issue tracker exclusively for bug reports and feature requests, however,
this issue appears to be a support request or question. Please ask on StackOverflow where the
community will do their best to help. There is a "material-ui" tag that you can use to tag your
question.
If you would like to link from here to your question on SO, it will help others find it.
If your issues is confirmed as a bug, you are welcome to reopen the issue using the issue template.
@awidjaja Tip: you need to use dangerouslySetInnerHTML when injecting the CSS.
@oliviertassinari
I didn't include the part of injecting to the html as I have already isolated the exact location of the disconnect between material-ui and JSS.
But alright, I don't need you to fix it, as this confirm my doubt in the beginning on the use of JSS. Even the installation generated so many errors, missing dependencies, etc. Such a waste of developer time.
I prefer to use emotion, a much better framework in all aspect. Will probably consider mui again in case you ever decide to move to emotion in the future, as long as it doesn't require the consumer to solve integration problem with the framework.
@awidjaja yes, I'm considering adding an emotion backend to our styling solution. Just need to figure out how it can be done. We took some tradeoff with JSS that makes it hard for people to get it right the first time. I'm looking into improving that. You can use emotion alongside JSS, there is nothing wrong with that. I would love to know more about your pain points. The escape problem one isn't on our side. Many people are doing SSR just fine with JSS.
@oliviertassinari
Great to hear that you plan to support emotion, I am sure many people would love it.
Please consider for the createMuiTheme to set a bunch of CSS custom variables instead of an object instance. Ideally one can use the createMuiTheme, a great tool, without having to install JSS dependencies, and then access the CSS custom variables from the custom components, either directly, or through, say, emotion ThemeProvider.
Then you will only need to update material-ui components to get the theme properties from the universal CSS custom variables and free people from having to use a particular css-in-js framework to pass the theme to the components. Then you can focus on building great components than having to make it work with a particular framework.
update: i was able to make it work using regex replace expression, and strangely when I removed the conversion it continued to work. Might be some problem during webpack bundling.
So, no problem with createMuiTheme returning escaped characters, react can handle it. I can now use both Material-UI theme helper and Emotion together.
This is the style injection code that works:
<style
id="jss-server-side"
dangerouslySetInnerHTML={{
__html: `${renderMeta.jssStyles}`,
}}
/>
@awidjaja I'm happy to hear it's working for you :). We are using the same approach for the Next.js example.
I haven't quite follow your point on the variables. You can inject muiTheme into the emotion theme.
@oliviertassinari
Yes, I am currently injecting muiTheme through emotion theme provider.
Currently each component library brings it's own css-in-js framework (jss, emotion, styled-components, etc.) and theme provider/consumer. Even if you only need to use one component, you'll have to add all the dependencies and add clutter to your react dom tree, and passing/sync the theme. This lead to higher development and maintenance efforts, higher bundle size, higher client's computation and memory footprint.
Imagine that one can have a universal theme of CSS custom variables that are automatically accessible by all components:
const theme = {
palette: {
primary: '#aabbcc'
}
}
const muiTheme = createMuiTheme(theme)
` : root {
--palette-primary-main: #aabbcc
--palette-primary-100: ...
...other variables
}
const StyledButton = styled(Button)`
background-color: var(--palette-primary-main, #ddeeff);
`
const StyledButton2 = styled(StyledButton)`
--palette-primary-main: var(--palette-accent-200);
background-color: var(--palette-primary-main, #ddeeff);
`
import { Button } from '@material-ui/core'
...
<Button primary>Click Me!</Button>
// the right CSS variables is auto assigned to the component's style
The CSS variables can also be injected to component using css/sass/css-modules (e.g. bootstrap, bulma. etc.).
Isn't that powerful?
You can check out #12827 for the support of CSS variables in the theme. Bulma, Bootstrap, Material-UI are competing libraires. There is little use cases for using two at the same time. I agree on your point regarding CSS-in-JS. In the next style iterations I want to allow people to use different styles backend, JSS, emotion, etc.
Most helpful comment
You can check out #12827 for the support of CSS variables in the theme. Bulma, Bootstrap, Material-UI are competing libraires. There is little use cases for using two at the same time. I agree on your point regarding CSS-in-JS. In the next style iterations I want to allow people to use different styles backend, JSS, emotion, etc.