Leverage runtime configurations
C3 Platform's Config types provide a very flexible and powerful way to define configurations at various levels, these configurations can drive logic in both back-end and front-end.
In order to understand how to use them in the front-end, we will cover the best practices when authoring your application's pages and components.
Glossary of relevant terms
- Site load time - All pages are rendered inside a UiSdlSite component, this component only loads once and the moment it loads marks the "Site load" time.
- Page load time - When you navigate between pages, the site will not be reloaded, but new pages will require their code to be loaded and when they do, it marks the "Page load" time.
- UI Feature flag Configs - Configurations that are loaded at the "Site load" time. These remix UiSdlApplicationConfig and are part of UiSdlConfig#app.
- Front-end specific Configs - Config values only used by the UI.
- Back-end Configs - Config values that are used to change server-side logic.
Impact on performance
Applications can have multiple configurations that enhance the development and user experience, but getting data from the server can be expensive, specially when the richness of the application requires several requests just to determine how the UI will be rendered.
For this reason, this document explains different approaches ranging from the best practices to the least recommendable but still valid cases.
UI Feature flag Configs
Config values that are needed for the majority of the application's pages can be preloaded if the config is front-end specific by remixing UiSdlApplicationConfig and adding as many configurations as needed. These configurations will be retrieved as part of UiSdlConfig and will be available on first render without performance impact.
This approach is only usable for front-end specific configs because they are nested in UiSdlConfig and you cannot add pre-existing back-end configurations as they are not ConfigChild types. For Config types that are driving back-end logic as well, you should check the Page specific Config options.
Example
First you'd have to define your app's feature flags
type MyAppUiFeatureFlags {
showCoolFeature: boolean
}And remix UiSdlApplicationConfig to add your own app's feature flags
remix type UiSdlApplicationConfig {
myApp: MyAppUiFeatureFlags
}Then in your component metadata you can conditionally render your component based on a feature flag with UiSdlFeatureFlagCondition, a condition type that uses a config value from UiSdlApplicationConfig.
In the following example we show a default empty state component UiSdlEmptyState but you can render any other component you want or just hide it by not passing the elseComponent field.
{
"type": "UiSdlConnected<UiSdlConditionalRenderer>",
"component": {
"condition": {
"type": "UiSdlFeatureFlagCondition",
"expectedValue": true,
"configPath": ["myApp", "showCoolFeature"]
},
"thenComponent": {
"id": "MyApp.CoolFeature"
},
"elseComponent": {
"id": "SDL.EmptyState",
"descriptionText": "This feature is not available yet"
}
}
}Sharing Configs from back-end to front-end
If you need to use Config values that cannot be included in UiSdlApplicationConfig, you should treat them as data and include them in a UiSdlApplicationState instance that drives your pages.
With UiSdlApplicationState, you can load any data into the state through epics and reducers and you can wait for your data to be loaded through a combination of UiSdlConditionalRenderer and UiSdlSpinner or UiSdlEmptyState.
React Components
Components written in TSX (customInstance or mixing UiSdlComponent) can directly call UiSdlUseConfig#useConfig to retrieve the values they need but it is important to minimize its use and it is advised to use in combination with global configs so they are retrieved at site load and not when the component is trying to render.
The UiSdlUseConfig#useConfig hook can be called with different parameters that change the behavior of the Config retrieval. The recommended variants are:
useConfig("UiSdlConfig", "app.myPkg.myConfig", null, true). Extend UiSdlConfig#app through remixing UiSdlApplicationState. The config will be preloaded and no extra requests are needed.useConfig("MySingletonConfig", "configPath", null, true). This requires the Config type to mixin DefaultInstance and the config will be retrieved from the server at first component render, all config paths are preloaded and if you call useConfig multiple times for the same Config type, only one request will be made.useConfig("MyConfig", "configPath", "configId"). Your config type is not a singleton, useConfig will send a request to get a single config value from the server. If you call it multiple times for the same type, each configPath will make a separate request.
If you need more control over how the config is retrieved, you should use the same approach as with "Sharing configs from back-end and front-end" by using UiSdlApplicationState