oscar-soderlund-373354-unsplash-436082-edited

AEM with Vue.js - Making Front-End Developers Happy at Last

Ramiro Matteoda, September 13, 2018

Who doesn’t enjoy Happy Hour? Drinks are cheaper, snacks tastes better, and everyone is in a good mood because it’s the end of the day. But that kind of happy has been elusive for front-end developers working with Adobe Experience Manager (AEM)…until now.

AEM is useful for creating a content management system that gives you one place to create, manage, and deliver digital experiences across websites. It provides reliable tools that power content and user management. However, we haven’t had a good solution for JavaScript templating inside it for front-end performance and productivity because AEM's out-of-the-box tools can't keep up with the rapid advances in the front-end world. As a result, front end developers have struggled and wasted precious time, while wondering how to better handle of the front-end part of an AEM site.

Their struggle is over, and it’s soon to be Happy Hour for front-end developers when they start using Vue.js with Vuex with AEM. Vue.js components are ideal for creating web applications with complex client-side interactivity. Using Vuex gives us a state management pattern for storing content information.

Read on to learn more about Vue.js and Vuex, when to use them, and how they help.

What Is Vue.js?

Vue.js is a progressive JavaScript framework for building user interfaces. Unlike monolithic frameworks, Vue.js is designed from the ground up to be incrementally adaptable. The core library is focused on the view layer only, and Vue.js makes it easy to pick up and integrate with other libraries or existing projects.

Vue.js uses an HTML-based template syntax that allows you to declaratively bind the rendered DOM to the underlying Vue.js instance’s data. The templates code is similar to that of AEM HTL components and can be combined with it power AEM Components.

If you’d like to know more, try out Vue.js using the JSFiddle Hello World example. Go to the Geting Started guide at Vue.js to learn how. 

What Is Vuex?

While Vue.js is a framework, Vuex is a state management pattern + library for Vue.js applications. It serves as a centralized store for all the components in an application, with rules ensuring that the state can only be mutated in a predictable fashion.

Having multiple components that share a common state can be a problem because multiple views might depend on the same piece of state needed to mutate it. With Vuex, we extract the shared state out of the components and manage it in a global singleton. This way, our component tree becomes a big view, and we give our code more structure and maintainability.

The diagram below shows the basic idea behind Vuex, as inspired by Flux, Redux and The Elm Architecture:

AEM Vuex Diagram 1

When to Use Vue.js.

Although Vue.js and Vuex help us deal with client-site interactivity and shared state management, they come with a cost due to more concepts and boilerplate, so you only want to use them when necessary.

If your system and components are simple, you probably don’t need Vue.js, because you can get by with a simple ClientLibs with JavaScript. But if you are building a medium-to-large-scale application with client-side interactivity and performance, and you’re sharing information between components and views with state management, using Vue.js and Vuex will help. As Dan Abramov, the author of Redux, says: “Flux libraries are like glasses: you’ll know when you need them.”

AEM Components with Vue.js and Vuex.

AEM combined with Vue.js and Vuex enables building highly interactive web pages with a professional authoring tool. To see how this works, let’s bring all three technologies together to create components that combine HTL and Vue.js, and share the state through multiples views using Vuex.

The AEM 6.4 project was created by using lazybones, and Webpack was integrated to improve the front-end development and deploy.

The next diagram shows how we integrate Vue.js and Vuex into the AEM System:

 AEM Vuex Diagram 2

The front-end part of AEM contains the HTL Components and Vue.js Components (HTL with Vue.js). The center of every AEM/Vuex application is the store. A store is basically a container that holds your application state (AEM content and user inputs).

Vuex stores are reactive. When Vue.js components retrieve state from it, they will reactively and efficiently update if the store's state changes. You cannot directly mutate the store's state. The only way to change a store's state is by explicitly committing mutations. This ensures every state change leaves a track-able record.

Upon Page loaded, components render HTML code and use information from the store if needed. The Vuex actions make async REST call to AEM to get content from AEM and build the store. When the REST call inside actions ends successfully, it triggers a state change by committing mutations. The store state is reactive and updates the view layer in each component.

To support the state management pattern in AEM a Vue.js ClientLib was added to the project. This ClientLib contains the main Vue.js app that includes reference to all components and the store modules.


import Vue from 'vue'
import components from './components.js'
import store from './store'

function startApp() {

  components.forEach(cmp => Vue.component(cmp.name, cmp.component));

  const elements = document.querySelectorAll('[data-component]');
  ([]).forEach.call(elements, (el) => {
    el.dataset.initialized = 'true';
    new Vue({
      el: el,
      store
    });
  });
}

document.addEventListener("DOMContentLoaded", startApp);

To better understand how the store works, notice that one of the modules in the store is dam.js. It contains a list of assets from AEM. This asset list is retrieved on Page loaded with a call to AEM Servlet that returns a JSON with all assets in a specific DAM folder configured by Authors. (For initial performance, include only path and name on each asset.)


import queryString from 'query-string';

const state = {
  assets: [],
};

const mutations = {
  setAssets(state, assets) {
    state.assets = assets;
  },
};

const actions = {
  getAssets({ commit }, assetsPath) {
  	const params = {
      ASSETS_PATH: assetsPath,
    };

    const urlService = `/bin/assetsStoreList?${queryString.stringify(params)}`;

    $.ajax ({
	    url: urlService,
	    dataType: "json",
	    contentType: "application/json",
	    success: function (jsonData) {
	        console.log("Vue.js DAM: get assets from AEM sucess");
	        commit('setAssets', jsonData);
	    },
	    error: function() {
	        console.log('ERROR on get assets from AEM instance ');
	    }
	});
  },
};

export default {
  state,
  mutations,
  actions,
};

With the asset list saved in the store, all asset paths and names are ready to be used in the view layer by Vue.js components. The asset list component that integrates AEM HTL component is configured by author and Vue.js component to build the view layer using data from the store.

Authors can configure the assets-path property that is passed to the Vue.js component assetlist.js that renders HTML code.

Next is the Vue.js Component code for assetlist that renders an HTML list with links to the assets in the DAM. All assets came from the Vuex store part of the app. This assets list is shared and could be used by other components. 


const assetslist = {
	name: 'assetslist',
	el: '#example-1',
	component: {
		props: ['assets-path'],
		template: `<ul id="example-1">
						<li v-for="asset in assets">
							<a :href="'http://localhost:4502' + asset.assetPath">
					
					</a>
				</li>
			</ul>`,
		computed: {
			assets() {
				return this.$store.state.dam.assets
			}
		},
		created(){
			this.$store.dispatch('getAssets','/content/dam/spavue');
		}
	} 
}

export default assetslist;

Note: You can find the project repository here.

It’s Time to Enjoy AEM Front-End with Vue.js!

As you have seen, it was quite simple to integrate Vue.js with Vuex into an existing AEM 6.4 project to create components with client-side interaction and better performance in the front end. Once the main Vue.js app is integrated using a ClientLib and the store is created, it’s easy for front-end developers to add new components, meaning they’ll enjoy their work more and might be done in time for Happy Hour. Drinks, anyone?

GET IN TOUCH

Topics: Adobe Experience Manager, Developer Think Tank, Development

Ramiro Matteoda

Ramiro is a Senior AEM Developer who loves to provide clients with tips for AEM best practices. Outside of work, he loves to swim.