Skip to content
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

[system] Pre-serialize & cache styles to improve performance #43412

Merged
merged 40 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
9045d66
draft: pre-serialize styles
romgrk Aug 23, 2024
f7d75a6
lint
romgrk Aug 23, 2024
e19bcf7
lint
romgrk Aug 23, 2024
61f432e
lint
romgrk Aug 23, 2024
2cf0557
lint
romgrk Aug 23, 2024
bce2ac0
refactor: lints
romgrk Aug 23, 2024
db0bf76
lint
romgrk Aug 23, 2024
c347735
refactor: add .isProcessed
romgrk Aug 27, 2024
0944431
lint
romgrk Aug 27, 2024
05d06da
Merge branch 'next' into perf-serialize-styles
romgrk Aug 27, 2024
6f3dfb5
Merge branch 'master' into perf-serialize-styles
romgrk Aug 27, 2024
25cfd5c
lint
romgrk Aug 27, 2024
1ef64d8
fix: style types
romgrk Aug 27, 2024
bd770e2
fix: build
romgrk Aug 27, 2024
30c33ab
fix: build
romgrk Aug 27, 2024
c3ab49e
lint
romgrk Aug 27, 2024
4fb397d
lint
romgrk Aug 27, 2024
a7a6ee5
ci: run (empty commit)
romgrk Aug 27, 2024
96fce69
lint
romgrk Aug 27, 2024
e09366c
Merge branch 'master' into perf-serialize-styles
romgrk Aug 28, 2024
509f086
refactor: internal_processStyle => internal_mutateStyles
romgrk Aug 30, 2024
1593d83
ci: run (empty commit)
romgrk Aug 30, 2024
c317ce0
Revert "refactor: internal_processStyle => internal_mutateStyles"
romgrk Aug 30, 2024
f2d05c1
Reapply "refactor: internal_processStyle => internal_mutateStyles"
romgrk Aug 30, 2024
4d0a5cb
Merge branch 'master' into perf-serialize-styles
romgrk Aug 30, 2024
bc451b8
deps: upgrade pigment-css
romgrk Sep 4, 2024
a31a272
Merge branch 'master' into perf-serialize-styles
romgrk Sep 4, 2024
5602d8d
Merge branch 'master' into perf-serialize-styles
romgrk Sep 12, 2024
ae000ae
ci: run (empty commit)
romgrk Sep 12, 2024
5a8a106
lint
romgrk Sep 12, 2024
3b74469
Merge branch 'master' into perf-serialize-styles
romgrk Sep 17, 2024
deca34f
Merge branch 'master' into perf-serialize-styles
romgrk Sep 18, 2024
79fd545
lint
romgrk Sep 18, 2024
2b52189
core: update deps
romgrk Sep 26, 2024
235993a
Merge branch 'master' into perf-serialize-styles
romgrk Sep 26, 2024
9ce6715
Merge branch 'master' into perf-serialize-styles
romgrk Sep 30, 2024
c1003b3
Merge branch 'master' into perf-serialize-styles
romgrk Oct 1, 2024
afd9442
Merge branch 'master' into perf-serialize-styles
romgrk Oct 2, 2024
0d220c4
Merge branch 'master' into perf-serialize-styles
romgrk Oct 2, 2024
080d166
Merge branch 'master' into perf-serialize-styles
romgrk Oct 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 3 additions & 28 deletions packages/mui-material/src/utils/memoTheme.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,6 @@
import { CSSInterpolation } from '@mui/styled-engine';
import { unstable_memoTheme } from '@mui/system';
import { Theme } from '../styles/createTheme';

type ThemeStyleFunction = (props: { theme: Theme }) => CSSInterpolation;
const memoTheme = unstable_memoTheme<Theme>;

// We need to pass an argument as `{ theme }` for PigmentCSS, but we don't want to
// allocate more objects.
const arg = { theme: undefined as unknown as Theme };

/**
* Memoize style function on theme.
* Intended to be used in styled() calls that only need access to the theme.
*/
export default function memoTheme(styleFn: ThemeStyleFunction) {
let lastValue: CSSInterpolation;
let lastTheme: Theme;

return (props: { theme: Theme }) => {
let value = lastValue;
if (value === undefined || props.theme !== lastTheme) {
arg.theme = props.theme;

value = styleFn(arg);

lastValue = value;
lastTheme = props.theme;
}

return value;
};
}
export default memoTheme;
5 changes: 4 additions & 1 deletion packages/mui-styled-engine-sc/src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,14 @@ export * from './GlobalStyles';
* For internal usage in `@mui/system` package
*/
// eslint-disable-next-line @typescript-eslint/naming-convention
export function internal_processStyles(
export function internal_mutateStyles(
tag: React.ElementType,
processor: (styles: any) => any,
): void;

// eslint-disable-next-line @typescript-eslint/naming-convention
export function internal_serializeStyles<P>(styles: Interpolation<P>): object;

// These are the same as the ones in @mui/styled-engine
// CSS.PropertiesFallback are necessary so that we support spreading of the mixins. For example:
// '@font-face'?: Fontface | Fontface[]
Expand Down
9 changes: 7 additions & 2 deletions packages/mui-styled-engine-sc/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export default function styled(tag, options) {
}

// eslint-disable-next-line @typescript-eslint/naming-convention
export const internal_processStyles = (tag, processor) => {
export function internal_mutateStyles(tag, processor) {
// Styled-components attaches an instance to `componentStyle`.
// https://github.com/styled-components/styled-components/blob/da8151762dcf72735ffba358173d4c097f6d5888/packages/styled-components/src/models/StyledComponent.ts#L257
//
Expand All @@ -46,7 +46,12 @@ export const internal_processStyles = (tag, processor) => {
if (tag.componentStyle) {
tag.componentStyle.rules = processor(tag.componentStyle.rules);
}
};
}

// eslint-disable-next-line @typescript-eslint/naming-convention
export function internal_serializeStyles(styles) {
romgrk marked this conversation as resolved.
Show resolved Hide resolved
return styles;
}

export { ThemeContext, keyframes, css } from 'styled-components';
export { default as StyledEngineProvider } from './StyledEngineProvider';
Expand Down
1 change: 1 addition & 0 deletions packages/mui-styled-engine/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"dependencies": {
"@babel/runtime": "^7.25.0",
"@emotion/cache": "^11.13.1",
"@emotion/serialize": "^1.3.1",
"csstype": "^3.1.3",
"prop-types": "^15.8.1"
},
Expand Down
5 changes: 4 additions & 1 deletion packages/mui-styled-engine/src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,14 @@ export type MUIStyledComponent<
* For internal usage in `@mui/system` package
*/
// eslint-disable-next-line @typescript-eslint/naming-convention
export function internal_processStyles(
export function internal_mutateStyles(
tag: React.ElementType,
processor: (styles: any) => any,
): void;

// eslint-disable-next-line @typescript-eslint/naming-convention
export function internal_serializeStyles<P>(styles: Interpolation<P>): object;

export interface SerializedStyles {
name: string;
styles: string;
Expand Down
12 changes: 10 additions & 2 deletions packages/mui-styled-engine/src/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable no-underscore-dangle */
import emStyled from '@emotion/styled';
import { serializeStyles as emSerializeStyles } from '@emotion/serialize';

export default function styled(tag, options) {
const stylesFactory = emStyled(tag, options);
Expand Down Expand Up @@ -27,13 +28,20 @@ export default function styled(tag, options) {
}

// eslint-disable-next-line @typescript-eslint/naming-convention
export const internal_processStyles = (tag, processor) => {
export function internal_mutateStyles(tag, processor) {
// Emotion attaches all the styles as `__emotion_styles`.
// Ref: https://github.com/emotion-js/emotion/blob/16d971d0da229596d6bcc39d282ba9753c9ee7cf/packages/styled/src/base.js#L186
if (Array.isArray(tag.__emotion_styles)) {
tag.__emotion_styles = processor(tag.__emotion_styles);
}
};
}

const wrapper = [];
// eslint-disable-next-line @typescript-eslint/naming-convention
export function internal_serializeStyles(styles) {
wrapper[0] = styles;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Emotion only accepts an array as argument, but I want to avoid creating allocations that aren't useful.

Copy link
Member

@Janpot Janpot Sep 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could add this as a comment wherever you use this pattern? To avoid the next maintainer removing this 6 months from now.

return emSerializeStyles(wrapper);
}

export { ThemeContext, keyframes, css } from '@emotion/react';
export { default as StyledEngineProvider } from './StyledEngineProvider';
Expand Down
Loading
Loading