AEM Cloud Service - Url Shortening of React SPA

Goal 


Adobe Experience Manager 2021.10.5933.20211012T154732Z-210900 (Oct 12, 2021)

This post is on making necessary changes in React SPA generated by the maven archetype (https://github.com/adobe/aem-project-archetype) to shorten the URLs eg. /content/eaem-spa-short-urls/us/en/home.html to /us/en/home.html

For Vanity urls check this post





Solution


1) Create the React SPA maven project using following command...

mvn -B archetype:generate -D archetypeGroupId=com.adobe.aem -D archetypeArtifactId=aem-project-archetype -D archetypeVersion=31 -D aemVersion=cloud -D appTitle="Experience AEM Short URLs" -D appId="eaem-spa-short-urls" -D groupId="apps.experienceaem.sites" -D frontendModule=react -D includeExamples=n -D includeDispatcherConfig=n


2) Create script eaem-spa-short-urls\ui.frontend\src\components\appConstants.js with the following code to give App root url...

export const PROJECT_URL_ROOT = "/content/eaem-spa-short-urls";


3) Adjust Router code to add the shortened URL in eaem-spa-short-urls\ui.frontend\src\components\RouteHelper\RouteHelper.js

import React, {Component} from 'react';
import {Route} from 'react-router-dom';
import {AuthoringUtils} from "@adobe/aem-spa-page-model-manager";
import {PROJECT_URL_ROOT} from "../appConstants";

export const withRoute = (WrappedComponent, extension) => {
    return class CompositeRoute extends Component {
        render() {
            let routePath = this.props.cqPath;
            if (!routePath) {
                return <WrappedComponent {...this.props} />;
            }

            extension = extension || 'html';

            let paths = ['(.*)' + routePath + '(.' + extension + ')?'];

            if (!AuthoringUtils.isInEditor() && routePath.startsWith(PROJECT_URL_ROOT)) {
                paths.push(routePath.substring(PROJECT_URL_ROOT.length) + ".html");
            }

            console.log(paths);

            // Context path + route path + extension
            return (
                <Route
                    key={routePath}
                    exact
                    path={ paths }
                    render={routeProps => {
                        return <WrappedComponent {...this.props} {...routeProps} />;
                    }}
                />
            );
        }
    };
};


4) Adjust the code in Navigation components to create links to shortened urls eg. eaem-spa-short-urls\ui.frontend\src\components\Nav\Nav.js

class NavItem extends Component {
    render() {
        if(!this.props.path || !this.props.title || !this.props.url) {
            return null;
        }

        let url = this.props.url;

        url = url.substring(PROJECT_URL_ROOT.length);

        return (
            <li className="NavItem" key={this.props.path}>
                <Link className="NavItem-link" to={url}>
                        {this.props.title}
                </Link>
            </li>
        );
    }
}


5) Under the hood, app makes calls to AEM for the model.json eg. /content/eaem-spa-short-urls/us/en.model.json, however due to the shortened url it makes additional call for fetching the model.json using shortened one eg. us/en.model.json. To snub this additional request to server, extend the ModelClient, creating ShortURLModelClient in eaem-spa-short-urls\ui.frontend\src\index.js and ignore such requests....

class ShortURLModelClient extends ModelClient {
    fetch(modelPath) {
        //if the path does not start with /content (page editing) or /conf (template editing) return empty model
        if (modelPath && !/^\/content|^\/conf/.test(modelPath)) {
            return Promise.resolve({});
        } else {
            return super.fetch(modelPath);
        }
    }
}

const modelManagerOptions = {};

if (process.env.REACT_APP_PROXY_ENABLED) {
    modelManagerOptions.modelClient = new LocalDevModelClient(process.env.REACT_APP_API_HOST);
} else {
    modelManagerOptions.modelClient = new ShortURLModelClient(process.env.REACT_APP_API_HOST);
}


6) For handling the Resource mapping of URL eg. /us/en/home.html and do an internal redirect to the real url eg. /content/eaem-spa-short-urls/us/en/home.html, create the following etc/map entries (there are many ways to handle redirects; on publish generally the preferred way is to use dispatcher rewrites,  dispatcher/src/conf.d/rewrites/rewrite.rules). However to keep things simple, adding an etc/map entry in eaem-spa-short-urls\ui.content\src\main\content\jcr_root\etc\map\https\author-p10961-e90064\.content.xml

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
    jcr:primaryType="sling:Mapping"
    sling:internalRedirect="/content/eaem-spa-short-urls/us/"
    sling:match="author-p10961-e90064.adobeaemcloud.com/us/"/>

No comments:

Post a Comment