Overrides and code injection in Spire

As a developer, you can create new handlers to inject into handler chains to extend Spire. You also have other ways you can override/extend code in Spire.

Widgets and pages

Collectively, Optimizely considers widgets A pre-configured content holder ISC_Content user roles may use to add content to website pages without having to develop page elements. and pages in Spire as ContentItems. ContentItems are defined in a typescript file, which includes all the information for editing a ContentItem, as well as rendering it on the storefront. Review the following basic example of a widget.

// a widget is a react component. It can be a class or functional component. It can be wrapped in HOCs
const ExampleWidget: React.FC<WidgetProps> = (props: WidgetProps) => {
    return <div>
        {props.fields["textFieldValue"]}
    </div>;
};
// the definition tells spire information it needs to allow this widget to be added to a page and edited.
// the basics of a definition include a group name and any fields that will exist on the widget
// the values for these fields are supplied by a CMS user and versioned and published.
const definition: WidgetDefinition = {
    group: "Testing",
    fieldDefinitions: [
        {
            name: "textFieldValue",
            editorTemplate: "TextField",
            fieldType: "General",
            defaultValue: "",
        },
    ],
};
// A widget's default export must be a WidgetModule
const widgetModule: WidgetModule = {
    component: ExampleWidget,
    definition,
};
export default widgetModule;

Server-side rendering

If you want to render a component server-side, you should be aware of the following items:

  • Using a react class component and the UNSAFE_componentWillMount lifecycle method is the recommended way to load data that the component needs to render server-side.
    • This UNSAFE_ function is part of React and we use it extensively. It should not be confused with Spire code that has been prefixed with UNSAFE_.
    • It is important that the component check if the data is loaded before loading it. Without this check, the component will get mounted, rendered then create a new request to load data 10 times before Spire gives up on it finishing. For example:
      UNSAFE_componentWillMount() {
          if (!props.isDataLoaded) {
              props.loadData();
          }
      }
  • The React hook useEffect, and the lifecycle method componentDidMount do not currently work with server-side rendering, so you cannot use these to load any data the component needs.

See Server-Side Rendering (SRR) Guidelines for Spire for more details.

Replacing items in content-library

Spire contains a core version of all out-of-the-box widgets, pages and components in a module called Content-Library. You may replace every file that is in Content-Library by a Blueprint, but you may not replace React components that live outside of Content-Library.

Replacing a Content-Library file involves creating the replacement at:
[blueprint]\src\Overrides\[pathOfReplacedFile]

For example, replace content-library\src\Widgets\Basic\PageTitle.tsx by creating [blueprint]\src\Overrides\Widgets\Basic\PageTitle.tsx.