Using CMS blocks effectively in Vue Storefront

Javier
ITNEXT
Published in
6 min readAug 12, 2019

--

Photo by Esther Jiao on Unsplash

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.
  • 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:

Refactored CMS block in the frontend

Keep in mind that node-html-parser favours performance over anything else so it only exposers a simplified subset of the APIs available to query HTML elements, but I haven’t found this to be a limitation.

Bonus!

Depending on where you use CMS blocks you might notice that they don’t load with the page after a full reload.

CMS block loads after page load

This is because this blocks are not loaded server side so they’re not part of the initial DOM content. We can’t prefetch the CMS data in asyncData in our component or mixin because this only runs for the top-most component and its mixins but we can move this login into the page component where it’s being used, in our case the Home.vue component:

Rendering CMS blocks on the server

Dispatching the cmsBlock/list action with an array of all the CMS blocks that we need in the page will make sure that the block’s data is available before load.

Keep in mind the asyncData method will be replaced with serverPrefetch in a later version of Vue Storefront

Server rendered CMS block in the frontend

Cool kids these days are using standalone CMS solutions like WordPress or Contentful to manage content in Vue Storefront sites but I think this is a very lightweight approach that you can take if you’re already using Magento 2 to manage your e-commerce site.

Feel free to use and contribute to the module if you find it useful, PRs and suggestions are more than welcome! 👋🏽

--

--

Full-stack developer specialized in blockchain and web3 development. BTC Ordinals client contributor.