-
-
Notifications
You must be signed in to change notification settings - Fork 400
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
Full static extraction to CSS file while keeping all dynamic parts intact. #579
Comments
Perhaps inspiration can be gotten from babel-plugin-css-in-js. The only significant downside with this plugin is that usage with webpack-dev-server (and hot module reloading enabled) does reload the page, as compilation is done in two steps.
It's definitely a good improvement, but it can also be made better. |
Additional thoughts: if we are not allowed to use any dynamic capabilities like function values etc which can access render time variables, why not put js styles in separate files, name them something.styles.js and just write a small script to extract them into css files, it is a few lines of code and not worth creating a package/library for it. You would need to
Update:
|
As far as I understand, having the static styles in a different file would essentially be the same as any SCSS/SASS file, except in JavaScript. The main benefit being that you don't need to set up any loaders and linters for those. It's still a very nice improvement, but for me the first reason to use JSS is to eliminate unused styles from being present in whatever is served to the user. Dead code elimination simply doesn't work with CSS (unless I missed something) and with JavaScript it's already present (provided you don't mess it up yourself). Do you think that would still work with separate JSS style files? |
There are 2 types of unused styles:
1. Styles you didn't use yet, for e.g. during ssr single pass.
2. Styles you never use
Currently we don't do any of these. Uglify will not drop any styles
property because it doesn't know if a corresponding classes.rule is used or
not.
For SSR we could add something to JSS, evtl. as a plugin for e.g. using
getters or proxy that can mark rules as used. In that case separate file or
the same doesn't matter.
In case of dead code, there are 2 possibilities:
1. Define each rule as a separate variable: var btnCls = css(...) so that
uglify can see an unused reference. Also eslint has a rule for that. This requires a different API.
2. Write an eslint rule which is smarter and can check for usage in classes
map. It will have to know jss, react-jss, styled-jss interfaces. It can as
well work with external files.
|
Update the original description, since I see that we can actually keep both static extraction and dynamic styles accessing the runtime. |
I think there are 2 ways to handle this:
I think the first solution is the most logical solution for initial implementation and eventually, the plugin can get smarter about it. |
@satya164 I was thinking to not evaluate function values at all and always keep them dynamic and warn the user if his ordering is going to be broken, based on prop names and dynamic values. |
Yeah, that's mostly what I meant by the first one :) |
Updated again, I figured out with help from @giuseppeg that
|
Hi, |
@kof Isn't extracting styles during webpack compilation too overcomplicated? Maybe extracting static styles during server startup to one big sheet and adding information about 'critical' classnames to components uuids will be better? I think that creating hash with components class names improve hydration performance - client won't have to manually remove SSR stylesheet after hydration Consider this: const {css} = createSheet();
const {classes} = css(
{
base: {
display: 'initial',
background: 'red',
},
green: {
background: 'green',
},
},
);
const Component = () => <div className={classes.base} />;
const CSS = await sheet.compileCSS();
// which compiles to something like it:
{
__styles: `
.c0 {
display: initial;
background: red;
}
.c1 {
background: green;
}
`,
...
[componentUUID]: {
base: 'c0',
green: 'c1',
}
...
}
runServer(CSS); |
Any update on this? |
The idea is to optimize it in a way that shifts preprocessing runtime overhead to the build stage, while keeping all dynamic parts working. It includes 2 stages: one is babel plugin, another is webpack plugin.
With full extraction,:
With babel plugin only there will be no runtime processing of static styles, only dynamic. Current state is that jss core without plugins with styles object vs preprocessed version of the same object results in 50% performance boost.
Exmple
Todo babel plugin
@raw
rule into the styles declarationTodo core
classes
to createStyleSheet@raw
plugin, add it to default preset@raw
with equivalent style objectsTodo webpack plugin
@raw
ruleFuture enhancements
{padding: (props) => props.spacing, paddingLeft: 10}
after compilation paddingLeft will be overwritten by padding since it will have higher source order specificityjss/static
for a reduced version of jss which does not include any plugins etc logic, since it is all preprocessed (unless we can treeshake it???)Some inspiration can be taken from
https://github.com/4Catalyzer/css-literal-loader
https://github.com/callstack-io/linaria
https://www.npmjs.com/package/extract-jss-webpack-plugin
The text was updated successfully, but these errors were encountered: