Skip to content
This repository was archived by the owner on Mar 4, 2020. It is now read-only.

perf: use memoized renderRule() #2044

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 23 additions & 0 deletions packages/react/src/components/Provider/Provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,14 @@ export interface ProviderProps extends ChildrenComponentProps {
target?: Document
theme?: ThemeInput
variables?: ComponentVariablesInput
unstable_performanceBits?: number
}

export const PerformanceBitCacheThemeVariables = 0x1 // not implemented yet
export const PerformanceBitMemoizeFelaStyles = 0x2
export const PerformanceAllBits =
PerformanceBitMemoizeFelaStyles | PerformanceBitCacheThemeVariables

/**
* The Provider passes the CSS-in-JS renderer, theme styles and other settings to Stardust components.
*/
Expand Down Expand Up @@ -76,10 +82,12 @@ class Provider extends React.Component<WithAsProp<ProviderProps>> {
disableAnimations: PropTypes.bool,
children: PropTypes.node.isRequired,
target: PropTypes.object,
unstable_performanceBits: PropTypes.number,
}

static defaultProps = {
theme: {},
unstable_performanceBits: 0,
}

static Consumer = ProviderConsumer
Expand Down Expand Up @@ -153,6 +161,7 @@ class Provider extends React.Component<WithAsProp<ProviderProps>> {
target,
theme,
variables,
unstable_performanceBits,
...unhandledProps
} = this.props
const inputContext: ProviderContextInput = {
Expand All @@ -167,6 +176,20 @@ class Provider extends React.Component<WithAsProp<ProviderProps>> {
// rehydration disabled to avoid leaking styles between renderers
// https://github.com/rofrischmann/fela/blob/master/docs/api/fela-dom/rehydrate.md
this.outgoingContext = mergeContexts(incomingContext, inputContext)
this.outgoingContext.unstable_performanceBits = unstable_performanceBits

if (process.env.NODE_ENV !== 'production') {
console.log(
[
'@stardust-ui/react: following performance optimizations are turned on:',
unstable_performanceBits & PerformanceBitCacheThemeVariables && '- cache theme variables',
unstable_performanceBits & PerformanceBitMemoizeFelaStyles &&
'- memoize calls to Fela to avoid plugin execution',
]
.filter(Boolean)
.join('\n'),
)
}

this.renderStaticStylesOnce(this.outgoingContext.theme)

Expand Down
12 changes: 11 additions & 1 deletion packages/react/src/lib/felaRenderer.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { callable } from '@stardust-ui/react-bindings'
import { createRenderer as createFelaRenderer } from 'fela'
import felaPluginEmbedded from 'fela-plugin-embedded'
import felaPluginFallbackValue from 'fela-plugin-fallback-value'
import felaPluginPlaceholderPrefixer from 'fela-plugin-placeholder-prefixer'
import felaPluginPrefixer from 'fela-plugin-prefixer'
import felaPluginRtl from 'fela-plugin-rtl'
import memoize from 'fast-memoize'

import { Renderer } from '../themes/types'
import felaDisableAnimationsPlugin from './felaDisableAnimationsPlugin'
Expand Down Expand Up @@ -77,6 +79,14 @@ const rendererConfig = {
],
}

export const createRenderer = (): Renderer => createFelaRenderer(rendererConfig)
export const createRenderer = (): Renderer => {
const renderer = createFelaRenderer(rendererConfig) as Renderer
renderer.unstable_memoizedRenderRule = memoize((styles, direction) => {
return renderer.renderRule(callable(styles), {
theme: { direction },
})
})
return renderer
}

export const felaRenderer = createRenderer()
19 changes: 16 additions & 3 deletions packages/react/src/lib/renderComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import createAnimationStyles from './createAnimationStyles'
import { isEnabled as isDebugEnabled } from './debug/debugEnabled'
import { DebugData } from './debug/debugData'
import withDebugId from './withDebugId'
import { PerformanceBitMemoizeFelaStyles } from '@stardust-ui/react'

export interface RenderResultConfig<P> {
ElementType: React.ElementType<P>
Expand Down Expand Up @@ -166,8 +167,13 @@ const renderComponent = <P extends {}>(
logProviderMissingWarning()
}

const { disableAnimations = false, renderer = null, rtl = false, theme = emptyTheme } =
context || {}
const {
disableAnimations = false,
renderer = null,
rtl = false,
theme = emptyTheme,
unstable_performanceBits = 0,
} = context || {}

const ElementType = getElementType(props) as React.ReactType<P>
const stateAndProps = { ...state, ...props }
Expand Down Expand Up @@ -230,7 +236,14 @@ const renderComponent = <P extends {}>(
}

if (renderer) {
classes[slotName] = renderer.renderRule(callable(resolvedStyles[slotName]), felaParam)
if (unstable_performanceBits & PerformanceBitMemoizeFelaStyles) {
classes[slotName] = renderer.unstable_memoizedRenderRule(
resolvedStyles[slotName],
direction,
)
} else {
classes[slotName] = renderer.renderRule(callable(resolvedStyles[slotName]), felaParam)
}
}
})

Expand Down
4 changes: 3 additions & 1 deletion packages/react/src/themes/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,9 @@ export type ThemeComponentStylesPrepared = {
} &
Record<string, ComponentSlotStylesPrepared | undefined>

export interface Renderer extends FelaRenderer {}
export interface Renderer extends FelaRenderer {
unstable_memoizedRenderRule: (styles: Record<string, any>, direction: string) => string
}

// ========================================================
// Fonts
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,5 @@ export interface ProviderContextPrepared {
target: Document
theme: ThemePrepared
originalThemes: (ThemeInput | undefined)[]
unstable_performanceBits?: number
}