CMS blocks are a popular way to enable users to edit elements in their Magento 2 websites from the backend, it requires (almost) no coding skills and provide a relatively safe way of updating content without risking breaking your e-commerce site.

Out of the box Vue Storefront provides support for CMS blocks, if you’re using the official Magento 2 VS Indexer or mage2vuestorefront data pump (v1.6+) CMS blocks and pages are synced to the Elastic Search database so we can query this data very efficiently.

Vue Storefront also includes a component to help us render this content anywhere in our sites, let’s see how that would look if we wanted to make one of the blocks in the homepage editable from a CMS block:

1. Use CmsBlock component

Using CmsBlock component in Vue Storefront

I chose the PromotedOffers component to make the left-most banner editable, so I replaced it with the <cms-block /> component that takes an identifier (or id ) prop that corresponds to the identifier in the Magento 2 admin area.

All this component does is display the content of the CMS block, keep in mind this will render the HTML as-is so we need to make sure it matches the structure that the Vue Storefront theme expects so it looks good:

2. Create CMS Block

CMS block markup from Magento 2 backend

Make sure the CMS blocks identifier matches the one in Vue Storefront

After saving this and making sure it’s indexed into the Elastic Search database you’ll be able to see the block in the homepage with the new content:

Photo by Sonnie Hiles on Unsplash

This works for a lot of use cases however the biggest drawback is, like mentioned earlier, that the <cms-block /> component will render the block’s content as HTML so Vue can’t really reach it, this means that we won’t be able to use any of the Vue Storefront goodness like:

Routing

Lazy loading

Custom components (like carousels, popups, etc)

Custom bindings

Events, etc…

This also makes CMS blocks harder to maintain because you need to keep a lot of markup in its content, so it can easily be changed by mistake and break the layout of the website.

Luckily thanks to the modular approach of Vue Storefront we can solve this problem easily.

CMS Block Mixin

The default CMS Block component does most of what we want out of the box, the only thing we need is a way to parse the content so we’re able to “pluck” out the elements that we need and use them however we want in our Vue Storefront components.

I figured this would be a common use case so I created a standalone mixin to parse the CMS block content from a string into something that can be more easily manipulated from the frontend.

I’m using the node-html-parser library to convert the CMS block content into a simplified DOM tree, this means we have access to some of the same low level APIs that we use to query HTML elements:

Node HTML parser example

With this at hand we can refactor our CMS block implementation, let’s start with the actual markup this time.

1. Update CMS block content

Updated CMS block content

As you can see now the content has been simplified quite a bit, since we’ll be able to parse this more easily we don’t need to worry about classes, attributes, inline content, etc. In fact the markup almost doesn’t matter now, notice how we’re using an <img> now even though we’ll need it later as a background-image in the frontend.

2. Using the new CMS Block Mixin

Let’s change our <cms-block /> to use a custom component we’ll create later, just to keep things more organised:

Updated CMS block component

Since the implementation of the CMS Block Mixin is pretty much the same as the built in <cms-block /> component nothing much has changed here, however the LeftBanner component is what makes all the magic happen:

Make sure you’ve ran yarn add vsf-cms-block-mixin before the next step

Updated CMS block component

As you can see vsf-cms-block-mixin exposes a parsedContent property that let’s you query elements in a similar way as you’d do in the DOM, so instead of rendering plain HTML we’re actually using Vue Storefront components to display our data, this means:

We’ve moved the complexity to the frontend, so content is easier to update.

We’re can make the most out of Vue components, see how we’re using v-lazy to lazy load the background image and <router-link> to render the link without a full page reload.

to lazy load the background image and to render the link without a full page reload. The CMS block’s content doesn’t have to follow the same structure as the frontend, as long as it can be queried it can be stored however you want.

The end result looks the same as before but this time we can see we’re dealing with a real Vue component: