Showing posts with label AEM Project. Show all posts
Showing posts with label AEM Project. Show all posts

March 30, 2021
Estimated Post Reading Time ~

Understanding the divide between AEM front-end and back-end developers

If you ask any front-end developer what they need to be successful, they'll likely tell you the three things:
  1. A rapid prototyping tool.
  2. A JSON end-point to grab data.
  3. A template language that makes sense.
  4. Don't tell me how to do my job.
If you ask any back-end developer what they need to be successful, they'll likely tell you they need three things:
  1. Ability to leverage Java / whatever frameworks to make them highly efficient.
  2. A good testing / CI / automation process.
  3. Not too much business, front-end, or ops noise.
  4. Don't tell me how to do my job.
AEM is built around experiences (FE) but powered through rich and deep integrations (BE) that keep businesses productive. How does a business consume CRM data? It's not through the front-end.

This is where we have to think about MVC at a macro level. FE might be asking for data in a concise JSON feed that can be consumed by a hot new template language (V), but BE is talking OSGi, separation of concerns, and scale-ability (C). Where the data is coming from is anyone's guess. If you live in the AEM world, you're hoping the JCR is building models the way you want (M). So whose domain is the model? I'd argue it's FE.

As an FE developer (FED), I build the dialogs that POST against SlingPostServlet and store my data exactly how I want. Do I want 45 properties outlining how this component should behave in responsive views or should I break them out as children? What does that mean for the back-end?

We're getting closer to a scenario where all parties can agree. FEDs just want a JSON end-point and a template language they're use to (JSX, HBS, whatever). BED's want to write productive Java classes (POJOs, Servlets, OSGi services). We just seem to be missing that final link. HTL is so incredibly powerful when rendered server-side, but doesn't satisfy the need of in-page updating. How do I sort a list without a query param and a page refresh? Angular? Handlebars? React? All of these solutions have felt like after thoughts or had down-sides when coupled with HTL.

At some point, the power of the back-end needs to be coupled with the front-end. Exposing the entire JCR tree to the front-end or writing servlets for every single view is not the answer.


By aem4beginner

Building a simple and scaleable ultra-modern front-end build system for AEM

Front-ends for AEM pre-2017

If you've paid attention to the front-end world within AEM you've likely seen blogs to integrate grunt or gulp. These solutions are good starts, but don't solve many problems.

  • How do we write modern ES6 syntax?
  • What about linting?
  • How do we have good separation between authoring and publish clientlibs?
  • How do we support a multi-tennant lifestyle?
  • Why are we using tools that have overlap? i.e. NPM and Bower

My front-end proposal scales better than most solutions while supporting ultra-modern front-end standards.

Modern front-ends for AEM in 2017

Let's talk tools, the whys, and then about the hows.

Tools

  • Dependency management: NPM
  • Task Runner: Webpack
  • Bundler: Webpack
  • Transpiling: Babel
  • Linting: ESLint + Airbnb Style Guide
  • Syntax: ES6 & LESS
  • Templating: TBD

Whys

We're using NPM instead of Bower because there's no longer a need for Bower... most FEDs understand package.json these days.

We're using webpack because it's a decent task runner and an excellent bundler... let's not use Grunt / Gulp to then run webpack... one tool. Webpack also doesn't need to be installed globally which makes on-boarding easier.

We use Babel to transpile our ES6 into something browsers can understand. It's widely documented which, again, helps on-boarding.

We're using ESLint + Airbnb Javascript Style Guide so our code follows strict standards that are widely used and documented. Again, this helps on-boarding... the clearest path to having documentation for your own project is to leverage tools that already have exceptional docs.

ES6 is the future (technically the present), let's start using it. LESS is AEM friendly, so if we ever decide to use AEM's native LESS compiler, we're not having to re-write everything.

Templating... templating is a challenging one that I don't think has been solved sufficiently. Handlebars is a natural fit, but it misses the mark in certain contexts. If I'm doing a new AEM project today, I'm using HBS, but I'm yearning for something better.

Hows

So, how does all of this work?

The high level overview

  • We start with a simple folder for our area of concern... publish, author, theme, bu1, bu2, whatever.
  • It uses .content.xml, css.txt, and js.txt to create a proper clientlib.
  • It has src and dist folders in it.
  • Inside src are our source files to be run through eslint, babel, and webpack.
  • Our dist folder consumes the output.

About our clientlib definition

If you've never worked with AEM, you might just think it's OK to drop a script tag on your page and be done. Unfortunately, you will end up hobbling AEM functionality and make more work for your back-end developers. Wrapping your JS (minified or not) inside a proper clientlib is incredibly important and will reduce work in the long run. Certain granite views are built around consuming a namespaced clientlib, and if you wish to view the raw JS files on non-dispatched servers (i.e. 4502), BE winds up needing to write content disposition configs because AEM serves up raw JS as attachments when they're not proper clientlibs.

Proxied Clientlibs

We add a property to our clientlib definition to allow it to be proxied out to /etc.clientlibs/. This reduces folder traversal... we're no longer digging into /etc/clientlibs/ourproject and /apps/ourproject/components. Everything just sits in /apps/ourproject/clientlibs and /apps/ourproject/components.

The .content.xml

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="cq:ClientLibraryFolder"
allowProxy="{Boolean}true"
categories="[pugranch.common.publish]"/>

Our webpack config

The basics is that we have entries, outputs, rules, and plugins.

The entries exist in the src folder, outputs go in the dist folder, rules and plugins should be fairly readable...

/**
* Pug Ranch Client Library Build System
*/
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const project = './jcr_root/apps/pugranch/clientlibs';
module.exports = {
entry: {
'base/publish': [
`${project}/base/publish/src/js/app.js`,
`${project}/base/publish/src/less/app.less`,
],
'base/author': [
`${project}/base/author/src/js/app.js`,
`${project}/base/author/src/less/app.less`,
],
'base/theme': [
`${project}/base/theme/src/js/app.js`,
`${project}/base/theme/src/less/app.less`,
],
},
output: {
path: `${__dirname}/jcr_root/apps/pugranch/clientlibs`,
filename: '[name]/dist/js/app.min.js',
},
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['env'],
},
},
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
loader: 'eslint-loader',
options: {
failOnError: true,
},
},
{
test: /\.less$/,
use: ExtractTextPlugin.extract({
use: [{
loader: 'css-loader',
options: {
url: false,
minimize: true,
},
}, {
loader: 'less-loader',
options: {
url: false,
},
}],
}),
},
],
},
plugins: [
new UglifyJSPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new ExtractTextPlugin({ filename: '[name]/dist/css/app.min.css', disable: false }),
],
stats: {
colors: true,
},
};

With our three entries (clientlibs) we have a lot of ground covered while being separated into their areas of concern:

  1. Base Publish - All structure and base-level features consumed by all parties (authors, visitors, etc.)
  2. Base Author - All structure and base-level features that are only consumed by authors. Everything from TouchUI hacks to Dialog listeners.
  3. Base Theme - All LESS / JS that can be individualized based on a tenant's requirements (think font families, margin & padding sizes, etc.)

Developer on-boarding

With one maven command, everything is pulled in and setup to start working:

mvn clean install -PautoInstallPackage

Day-to-day development

Things differ a bit here for BE and FE. BE can continue to use the maven tools they're use to. FE can switch over to start using tools they're use to:

cd ui.apps
npm run aemlocal

<new terminal tab>

aemsync

By paring our aemlocal script (defined in package.json and basically calling webpack --watch) with aemsync, we can now build anything on the front-end without any maven cruft. Want to add a new dropdown to a dialog? No problem. Want to wire up a new some new javascript functionality? No problem. All of this syncs up seamlessly to AEM with perfect separation of concerns.

Source Code

Want to see how it all works? Go check the source code.



By aem4beginner