Livestream: Building landing pages with AI | 4/3

Announcing Visual Copilot - Figma to production in half the time

Builder logo
builder.io

Livestream: Building landing pages with AI | 4/3

Announcing Visual Copilot - Figma to production in half the time

Blog

×

Visual CMS

Drag-and-drop visual editor and headless CMS for any tech stack

Theme Studio for Shopify

Build and optimize your Shopify-hosted storefront, no coding required

Resources

Blog

Get StartedLogin

When you rely on custom components, sometimes you want to publish new versions and phase out previous versions. This document shows you how to version your custom components so that your team is using the most up-to-date iteration.

The following video shows two versions of a component in the Visual Editor and how, with minimal code edits you can deprecate one version in favor of another.

To version custom components, you should already be familiar with the following:

Always make new versions of custom components backward-compatible so that any content using a prior version of the component continues to work.

Builder uses the current version of the custom component when rendering your content because that is the version that exists on your site–even if the content was originally created with a prior version of the component.

For example, if the new version of the custom component has an additional input, make sure to handle the case where that input is undefined, since old content does not have a value for that input.

Importantly, even if you are deprecating a previous version of a component, keep that previous version registered with Builder so that any instances still in use continue to work properly.

The following code is a minimal first version of HelloWorldComponent with a single input called text.

// Original version that has a input called "text"
const HelloWorldComponent = (props) => <div>{props.text}</div>;

Builder.registerComponent(HelloWorldComponent, {
  name: "Hello World",
  inputs: [{ name: "text", type: "string" }], // <-- one input in this original version of the component
});

The updated HelloWorldComponent has a new description input, but keeps the text input. By keeping the original text input, HelloWorldComponent continues to support the previous version's text input.

// New version still supports the old input style, even though it has a new "description" input
const HelloWorldComponent = (props) => <div>{props.text}</div><div>{props.description || 'default description'}</div>;

Builder.registerComponent(HelloWorldComponent, {
  name: "Hello World",
  inputs: [
    { name: "text", type: "string" }, // <-- Keep orginal input to support previous content
    { name: "description", type: "string" } // <-- New input for v2
  ],
});

If a defaultValue is passed to an input, Builder only applies that value to new content that uses the new component–it is not retroactive. For more information on defaultValue, refer to the defaultValue description in Input Types in Builder.

When naming your custom components, including when introducing new versions, be sure to give each component a unique name. You can use completely different names such as Our Header and Our New Header, or you can use a naming technique that uses version numbers in your code while maintaining the same name, unchanged, in the Visual Editor.

To manage names and versions of custom components, we recommend the following workflow:

  1. Optionally hide the previous version of the component to prevent its use.
  2. Give the component(s) a version number for your reference in the defaultValue property.

To hide and assign a version number to your components, follow the steps for your framework:

To keep the same name in the Visual Editor while using version numbers in your code, you can prepend a version indicator such as number followed by a colon, :, in the name of the component in registerComponent().

The following example demonstrates removing the first version of a HeadingComponent from the Visual Editor and replacing it with a second version by the same name.

1. Set hideFromInsertMenu to true. In this way, the first version of this component doesn't show up in the Insert tab.

const Heading = props => (
  <h1>{props.title}</h1>
)


Builder.registerComponent(Heading, { 
  name: 'Heading', // <-- the name your users see in the Visual Editor
  hideFromInsertMenu: true, // <-- don't show in Insert tab
  inputs: [{ 
    name: 'title', 
    type: 'text',
    defaultValue: 'I\'m version 1' }]
})

2. Register the second version of the component. Keep the original version registered so any content that relies on it continues working as expected.

3. In the second component name, prepend the name that shows up in the Visual Editor with a version followed by a colon. In this example, the name is v2: Heading.

Builder.registerComponent(Heading, { 
  name: 'v2: Heading',
  inputs: [{ 
    name: 'title', 
    type: 'text',
    defaultValue: 'I\'m version 2' }]
})

Builder omits anything that you put before the colon, so you have flexibility in how you indicate versions.

If you have content that uses version one, that content still renders as long as you keep that original component registered; however, with hideFromInsertMenu set to true, the first version doesn't show up in the Visual Editor. Instead, the second version shows up, making sure users use the new version.

The full example is below:

const Heading = props => (
  <h1>{props.title}</h1>
)

Builder.registerComponent(Heading, { 
  name: 'Heading',
  hideFromInsertMenu: true,
  inputs: [{ 
    name: 'title', 
    type: 'text',
    defaultValue: 'I\'m version 1' }]
})

Builder.registerComponent(Heading, { 
  name: 'v2: Heading',
  inputs: [{ 
    name: 'title', 
    type: 'text',
    defaultValue: 'I\'m version 2' }]
})

The following is a screenshot of both versions of the HeadingComponent. The first version was added before it was deprecated by setting hideFromInsertMenu to true. and has the default value of "I'm version 1".

The second version replaced the first version with the same name in the Visual Editor, Heading, but the default value now says "I'm version 2".

The first version remains functional because it is still registered with Builder.

If the updates you want to make preclude backward compatibility, take the following steps:

  1. Create an entirely new component registered with a new name.
  2. Keep the previous version of the component registered with Builder so that existing content on your site using that component continues to function properly.
  3. Hide the old version of the component from the Builder editor so your team doesn't use the old version with newer content. To hide a component, use the hideFromInsertMenu option when registering the component, as in the following example code:
// Hide the original version
const HelloWorldComponent = (props) => <div>{props.text}</div>;

Builder.registerComponent(HelloWorldComponent, {
  name: "Hello World",
  hideFromInsertMenu: true, // <-- hides the original version
  inputs: [{ name: "text", type: "string" }],
});

// New version to use instead 
const HelloWorldComponentV2 = (props) => <div>{props.title}</div>;

Builder.registerComponent(HelloWorldComponentV2, {
  name: "Hello World V2",
  inputs: [
    { name: "title", type: "string" },
  ],
});

Tip: The content model for the component does not update automatically.

To phase out custom components while ensuring that contents using those components still work as intended, use the hideFromInsertMenu option so your component is no longer visible in the Visual Editor.

Continuing to register a deprecated component with Builder means Builder can still use your component for older content while teammates use the newer version that's in the Insert tab.

For more detail, see the entry on hideFromInsertMenu in Registering Custom Components.

// Hide the original version

Builder.registerComponent(MyDeprecatedComponent, {
  ...
  hideFromInsertMenu: true, // <-- keeps this component out of the Insert Tab
  ...
});

If you're iterating on your custom components, check out Input Types in Builder to get familiar with all the options available.

Was this article helpful?

Get the latest from Builder.io