Aggressively optimise client library to prevent handlebars enrichment where possible
This commit is contained in:
parent
83a337e20e
commit
be2ec9b427
4 changed files with 69 additions and 26 deletions
|
@ -23,6 +23,11 @@
|
||||||
// props with old ones, depending on how long enrichment takes.
|
// props with old ones, depending on how long enrichment takes.
|
||||||
let latestUpdateTime
|
let latestUpdateTime
|
||||||
|
|
||||||
|
// Keep track of stringified representations of context and instance
|
||||||
|
// to avoid enriching bindings as much as possible
|
||||||
|
let lastContextKey
|
||||||
|
let lastInstanceKey
|
||||||
|
|
||||||
// Get contexts
|
// Get contexts
|
||||||
const context = getContext("context")
|
const context = getContext("context")
|
||||||
const insideScreenslot = !!getContext("screenslot")
|
const insideScreenslot = !!getContext("screenslot")
|
||||||
|
@ -42,7 +47,9 @@
|
||||||
definition?.hasChildren &&
|
definition?.hasChildren &&
|
||||||
definition?.showEmptyState !== false &&
|
definition?.showEmptyState !== false &&
|
||||||
$builderStore.inBuilder
|
$builderStore.inBuilder
|
||||||
$: updateComponentProps(instance, $context)
|
$: rawProps = getRawProps(instance)
|
||||||
|
$: instanceKey = JSON.stringify(rawProps)
|
||||||
|
$: updateComponentProps(rawProps, instanceKey, $context)
|
||||||
$: selected =
|
$: selected =
|
||||||
$builderStore.inBuilder &&
|
$builderStore.inBuilder &&
|
||||||
$builderStore.selectedComponentId === instance._id
|
$builderStore.selectedComponentId === instance._id
|
||||||
|
@ -59,6 +66,16 @@
|
||||||
name,
|
name,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const getRawProps = instance => {
|
||||||
|
let validProps = {}
|
||||||
|
Object.entries(instance)
|
||||||
|
.filter(([name]) => !name.startsWith("_"))
|
||||||
|
.forEach(([key, value]) => {
|
||||||
|
validProps[key] = value
|
||||||
|
})
|
||||||
|
return validProps
|
||||||
|
}
|
||||||
|
|
||||||
// Gets the component constructor for the specified component
|
// Gets the component constructor for the specified component
|
||||||
const getComponentConstructor = component => {
|
const getComponentConstructor = component => {
|
||||||
const split = component?.split("/")
|
const split = component?.split("/")
|
||||||
|
@ -76,13 +93,23 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enriches any string component props using handlebars
|
// Enriches any string component props using handlebars
|
||||||
const updateComponentProps = (instance, context) => {
|
const updateComponentProps = (rawProps, instanceKey, context) => {
|
||||||
|
const instanceSame = instanceKey === lastInstanceKey
|
||||||
|
const contextSame = context.key === lastContextKey
|
||||||
|
|
||||||
|
if (instanceSame && contextSame) {
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
lastInstanceKey = instanceKey
|
||||||
|
lastContextKey = context.key
|
||||||
|
}
|
||||||
|
|
||||||
// Record the timestamp so we can reference it after enrichment
|
// Record the timestamp so we can reference it after enrichment
|
||||||
latestUpdateTime = Date.now()
|
latestUpdateTime = Date.now()
|
||||||
const enrichmentTime = latestUpdateTime
|
const enrichmentTime = latestUpdateTime
|
||||||
|
|
||||||
// Enrich props with context
|
// Enrich props with context
|
||||||
const enrichedProps = enrichProps(instance, context)
|
const enrichedProps = enrichProps(rawProps, context)
|
||||||
|
|
||||||
// Abandon this update if a newer update has started
|
// Abandon this update if a newer update has started
|
||||||
if (enrichmentTime !== latestUpdateTime) {
|
if (enrichmentTime !== latestUpdateTime) {
|
||||||
|
|
|
@ -14,18 +14,32 @@
|
||||||
const newContext = createContextStore(context)
|
const newContext = createContextStore(context)
|
||||||
setContext("context", newContext)
|
setContext("context", newContext)
|
||||||
|
|
||||||
$: providerKey = key || $component.id
|
const providerKey = key || $component.id
|
||||||
|
|
||||||
// Add data context
|
// Generate a permanent unique ID for this component and use it to register
|
||||||
$: newContext.actions.provideData(providerKey, data)
|
// any datasource actions
|
||||||
|
const instanceId = generate()
|
||||||
|
|
||||||
// Instance ID is unique to each instance of a provider
|
// Keep previous state around so we can avoid updating unless necessary
|
||||||
let instanceId
|
let lastDataKey
|
||||||
|
let lastActionsKey
|
||||||
|
|
||||||
// Add actions context
|
$: provideData(data)
|
||||||
$: {
|
$: provideActions(actions, instanceId)
|
||||||
if (instanceId) {
|
|
||||||
actions?.forEach(({ type, callback, metadata }) => {
|
const provideData = newData => {
|
||||||
|
const dataKey = JSON.stringify(newData)
|
||||||
|
if (dataKey !== lastDataKey) {
|
||||||
|
newContext.actions.provideData(providerKey, newData)
|
||||||
|
lastDataKey = dataKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const provideActions = newActions => {
|
||||||
|
const actionsKey = JSON.stringify(newActions)
|
||||||
|
if (actionsKey !== lastActionsKey) {
|
||||||
|
lastActionsKey = actionsKey
|
||||||
|
newActions?.forEach(({ type, callback, metadata }) => {
|
||||||
newContext.actions.provideAction(providerKey, type, callback)
|
newContext.actions.provideAction(providerKey, type, callback)
|
||||||
|
|
||||||
// Register any "refresh datasource" actions with a singleton store
|
// Register any "refresh datasource" actions with a singleton store
|
||||||
|
@ -43,10 +57,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
// Generate a permanent unique ID for this component and use it to register
|
|
||||||
// any datasource actions
|
|
||||||
instanceId = generate()
|
|
||||||
|
|
||||||
// Unregister all datasource instances when unmounting this provider
|
// Unregister all datasource instances when unmounting this provider
|
||||||
return () => dataSourceStore.actions.unregisterInstance(instanceId)
|
return () => dataSourceStore.actions.unregisterInstance(instanceId)
|
||||||
})
|
})
|
||||||
|
|
|
@ -4,7 +4,21 @@ export const createContextStore = oldContext => {
|
||||||
const newContext = writable({})
|
const newContext = writable({})
|
||||||
const contexts = oldContext ? [oldContext, newContext] : [newContext]
|
const contexts = oldContext ? [oldContext, newContext] : [newContext]
|
||||||
const totalContext = derived(contexts, $contexts => {
|
const totalContext = derived(contexts, $contexts => {
|
||||||
return $contexts.reduce((total, context) => ({ ...total, ...context }), {})
|
// The key is the serialized representation of context
|
||||||
|
let key = ""
|
||||||
|
for (let i = 0; i < $contexts.length - 1; i++) {
|
||||||
|
key += $contexts[i].key
|
||||||
|
}
|
||||||
|
key += JSON.stringify($contexts[$contexts.length - 1])
|
||||||
|
|
||||||
|
// Reduce global state
|
||||||
|
const reducer = (total, context) => ({ ...total, ...context })
|
||||||
|
const context = $contexts.reduce(reducer, {})
|
||||||
|
|
||||||
|
return {
|
||||||
|
...context,
|
||||||
|
key,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Adds a data context layer to the tree
|
// Adds a data context layer to the tree
|
||||||
|
|
|
@ -22,14 +22,6 @@ export const propsAreSame = (a, b) => {
|
||||||
* Data bindings are enriched, and button actions are enriched.
|
* Data bindings are enriched, and button actions are enriched.
|
||||||
*/
|
*/
|
||||||
export const enrichProps = (props, context) => {
|
export const enrichProps = (props, context) => {
|
||||||
// Exclude all private props that start with an underscore
|
|
||||||
let validProps = {}
|
|
||||||
Object.entries(props)
|
|
||||||
.filter(([name]) => !name.startsWith("_"))
|
|
||||||
.forEach(([key, value]) => {
|
|
||||||
validProps[key] = value
|
|
||||||
})
|
|
||||||
|
|
||||||
// Create context of all bindings and data contexts
|
// Create context of all bindings and data contexts
|
||||||
// Duplicate the closest context as "data" which the builder requires
|
// Duplicate the closest context as "data" which the builder requires
|
||||||
const totalContext = {
|
const totalContext = {
|
||||||
|
@ -41,7 +33,7 @@ export const enrichProps = (props, context) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enrich all data bindings in top level props
|
// Enrich all data bindings in top level props
|
||||||
let enrichedProps = enrichDataBindings(validProps, totalContext)
|
let enrichedProps = enrichDataBindings(props, totalContext)
|
||||||
|
|
||||||
// Enrich click actions if they exist
|
// Enrich click actions if they exist
|
||||||
if (enrichedProps.onClick) {
|
if (enrichedProps.onClick) {
|
||||||
|
|
Loading…
Reference in a new issue