Accelerated Mobile Pages (AMP) strategy/ implementation for AEM - mobile

What is the best approach/ strategy to implementing Accelerated Mobile Pages (https://www.ampproject.org/) within AEM 6.1 for a responsive web site that already renders for both desktop and mobile?
An initial concern is that you would be creating duplicate pages of content. So is it possible that AMP and normal html can share the same content?
Would you always redirect to AMP if mobile, and what is the best way to do that?
How would an author handle both AMP and standard pages?

More information is required to completely answer your question -
What is your approach towards responsive design (if you are supporting desktop)? Are mobile site and desktop site different?
What version of AEM are you using?
How would an author handle both AMP and standard pages?
Authoring is something which is not AMP specific, AMP is a feature/behavior that you would enforce on Publish instance and not Author. But this depends on your approach towards responsive behavior - single site handing both mobile and desktop or separate?
a) If there are separate sites then you would actually cater to AMP behavior on author as well by having different components/resource types and page templates for it (This is how prior to AEM 5.6 mobile sites were handled). I can provide more details if you are following this approach
b) If there is single site then you should configure this at publish only.
is it possible that AMP and normal html can share the same content?
In short Yes, depends on how you design your components and/or what version of AEM are you using. In AEM 6.2, Adobe has introduced content fragments that allows channel agnostic content management i.e. more like assets.
If you are not using AEM 6.2, even then you can allow for reusable content by designing for it. You could create a global space with content pieces and then use reference component to associate/use that content on different pages (the only challenge with this is to manage full text search if you have that on your site).
Would you always redirect to AMP if mobile, and what is the best way
to do that?
What ever approach you take a) or b) (as described in first answer), the essence for managing the redirects/rewrites is to exploit user-agent information in request. Apache/httpd allows to handle user-agent information and do a redirect of rewrite.
For approach a) you will redirect to your mobile site after identifying that user-agent is mobile user-agent and for approach b) you could rewrite the url (not redirect) add a selector that allows for you AMP specific resource scripts to render the content. Selector based solution is one possible way of implementing the single site for both web and AMP
UPDATE:
Assuming that you need to cache both AMP version and normal HTML markup, the solution is to use a special selector for rendering AMP version of markup. You could setup a component hierarchy -
Lets say your base page structure is abstracted out in a custom component called - AbstractPageComponent (this in most cases is replica of foundation/components/page customized to project need) and all your page components extend this component. What you could do is create another such component lets say AMPAbstractPageComponent, setup this page structure similar to standard Abstract component i.e. let it have its own copy of scripts head,body,content, header,footer etc. But make sure you name them differently from the convention in AbstractPageComponent, u could do that by pre-pending amp to them like amp-head.html, aem-body.html,amp-content.html. Then there will be AMPAbstractPageComponent.html the component rendering script that structures the page by including relevant AMP scripts and/or AbstractPageComponent scripts.
Each of these scripts should have the AMP specific logic and where-ever you need to refer to HTML logic include/defer to the AbstractPageComponent's script.
Now define the selector script to ensure AMP specific rendition, let say your selector is amp then in AbstractPageComponent create a amp.html or amp.jsp and in this script include AMPAbstractPageComponent.html
NOTE: The ideal structure to implement will be foundation Page -> AbstractPageComponent -> AMPAbstractPageComponent -> Other page templates
I have specified AMPAbstractPageComponent to be parent of AbstractPageComponent assuming that your site already exists and there is content pages referring to existing structure. If your site structure permits you to introduce AMPAbstractPageComponent between AbstractPageComponent -> Other page templates then you should do that and let AMPAbstractPageComponent handle that amp selector.
What i have defined above is the first level of change, next you need to consider the components inclusion that have AMP specific handling. For components included in templates you need pass on the selector amp if its coming in the URL otherwise included component will render their default script (component included in the templates not drag and dropped components).Dragged and dropped components will automatically try to render amp script if available and in case its not then default to its own script.
Please note, this is approach based on the selector resolution, for actual implementation to do AMP specific work you may have to do other stuff as well, another thing i have not included is the managing component rendering i.e if you normal html includes a parsys and that script in not included in your AMP implementation your components will not render. So you will either have to duplicate those inclusions in AMP specific scripts or you will have to include the AbstractComponent's scripts to include such components
Do a small PoC, I gave the approach solely based on high level understanding of what AMP does by reading the link you have specified.

I'm actually thinking about implementing the same and here is the thought path laid out so far (untested):
add new page extension handler at foundation/components/primary/cq/page (overlay it under /apps) named Page.amp.jsp with <%#include file="proxy.jsp" %> content
add page renderer into your application logic at the same place where are you rendering html pages
The rest should be done by ootb sling URL resolution handler

Related

How to set dynamic metatags in ReactJS to get nice share links?

The app
The application was made using ReactJS, React Router Dom, Styled Components and Redux ducks.
The backend we consume is also made by us using Amazon Amplify and GraphQL.
The goal
We need to define the meta tags of one of the application pages so that it is possible to share personalized links to users
in social networks using OpenGraphic meta tags and the like.
The problem
The project was made in ReactJS and ReactJS has only one HTML page as root (/public/index.html), in this way, everything is generated with Javascript in a root tag, and when it arrives in the browser it is transpiled, as we already know. The problem is that the crawlers responsible for understanding the meta tags are not able to understand Javascript and end up not finding the dynamic data that I am defining on the page that I need to share the link on. They understand that there is one html file and only.
Attempts to resolve the issue
1) Define the meta tags in the /public/index.html file itself
This solution doesn't work because the data we are using is dynamic and the index.html file is a static file
2) Using react-helmet
The solution allows meta tags to be defined, but as already mentioned, crawlers don't understand JS. So, despite being on the page, the meta tags do not appear when sharing the link.
3) Using some SSR technology
This is a possible solution, but we were unable to integrate any SSR Framework into React. And it is not feasible to change the base technology of the project. We can't just switch from React to Next, for example, as the project is already complete.
4) Using a small server made with express.js along with the React application to replace the meta tags in index.html with string.replace() simulating something like an SSR
This solution works, but it causes two requests to be made every time the page is accessed, once by express.js and once on the front-end side by React. Due to the number of requests increasing, this solution was discarded. But if necessary, you can do it. In this case it is also necessary to check if Amplify can keep the application and the small server running in the same project.
5) Using react-snap with react-helmet
React-snap allows you to create html snapshots of the pages of a React project based on their routes and links, this added to react-helmet generates a perfect solution for links to be treated well by web crawlers when they are shared. But the solution doesn't work with dynamic routes. For example, /your-route/:id is a dynamic route that expects an id to be fully defined. React-snap gets lost when trying to create a snapshot of a route that only exists when the id is set. Unfortunately, this solution doesn't work.
These were the solutions we used to try to solve the problem, but it was not possible yet. Probably attempt 4 would be the most ideal to solve the problem. But we are looking for the best way that will not generate reworks and future problems. If someone knows a better way to do that, would help us a lot!

Why is React Js called as Single Page Application

Hello guys i am new to React Js i often hear and see posts regarding react is single page app but never understood what is SPA and many say that it doesn't reload the pages but i didn't understood why so could you guys please explain me with simple examples.
A Single Page Application is a web application or website that interacts with the web browser by dynamically rewriting the current web page with new data from the web server, instead of the default method of the browser loading entire new pages.
This means that the URL of your website will not change completely (page will not reload), instead it will keep getting content and rewriting the DOM with it instead of loading a new page.
The goal is faster transitions that make the website feel more like a native app
Example: Netflix
This is the dashboard, and when we click on any movie, it changes to /watch and the content is rewritten.
In Technical Terms:
When building your react-app, you can see that there is only one
App.js from where your entire web-app is loaded in fragments and
components. This behaviour of rendering components and pages on a single page and changing the DOM( is a single page behaviour and hence the name), instead of loading a new page with new content, this makes it feel like a single application.
As mentioned in Glossary of React Terms:
A single-page application is an application that loads a single HTML page and all the necessary assets (such as JavaScript and CSS) required for the application to run. Any interactions with the page or subsequent pages do not require a round trip to the server which means the page is not reloaded.
And about "Why is React Js called as Single Page Application":
Though you may build a single-page application in React, it is not a requirement. React can also be used for enhancing small parts of existing websites with additional interactivity. Code written in React can coexist peacefully with markup rendered on the server by something like PHP, or with other client-side libraries. In fact, this is exactly how React is being used at Facebook.
A single page application has one single page e.g. www.google.ch. It is exactly one HTML file (with all its required dependencies) loaded into the browser. You'd navigate between paragraphs only using hash-router, but never ever visit another page like www.google.ch/maps (that would then be www.google.ch/#maps, which references / -> index.html) (tho google may not be the best example, it is more about URIs).
ReactJS is an open source JS library for building UI and used for SPA, and it manages the views of web apps. Reactjs can help you to modify your data without reloading of a page. It is a popular library in the market trend because of its scalability & fast performance.
Single Page applications are different from multiple page apps that we see everywhere because the SPA doesn't move into new pages; instead, it will load the pages inline within the same page.
In traditional websites, when we go from one page to another, the whole site is loaded. e.g - if you go from "www.example.com/hi" to "www.example.com/hello" the whole website is reloaded. No matter how much portion of the website is really changed. Let's say, the website has "Sidebar, logo, menu" on both of its pages, then the full reload doesn't make any sense. This takes too much time and decreases the performance.
Single Page Applications, as the name suggests, have only one single page that is loaded the first time you open the website. After this, no matter where you click, it is not gonna refresh the website fully.
browser reload button
The loading icon of the browser doesn't load when we move from one page to another on SPA site, as it does on the traditional websites.
Cons- SPA sites are great for UI UX but they are not the best when it comes to Search Engine Optimisation, it creates problems with rankings.

Render WordPress page builder blocks in Next.js / React.js?

Headless WordPress (CMS), that is use a page builder (Elementor, Gutenberg etc') to write content.
Then render the content elsewhere, using Next.js (React.js).
I can easily get the HTML markup, but the styling is challenging.
I could also get the inner data structure, for example Elementor is using JSON, but that means I should implement each component - unwanted.
How would you approach this, considering WP headless + Next.js is a requirement?
In a similar situation - there's no easy solution. Page builders are dependent on lots of WP-specific code. Unless you need specific WP plugins to power parts of this, it's probably a lot less work to adapt ApostropheCMS to whatever your needs are.

Add an additional page to an Angular SPA

The Scenario
I'm developing the front-end (CSS only) of an Angular SPA.
I'm not especially familiar with Angular routing.
I'd like to add a standalone page containing Bootstrap components just for development purposes (yes, I know this means it won't be a single page application anymore). This way I have one unified view with all the components so I don't have to switch back and forth while working on the CSS. It also acts as documentation for the Bootstrap for the other devs to refer to.
What I've tried
I originally added a bootstrap.html page to the app folder, alongside the app's index.html This worked at first, but has now stopped working. What would be the best/standard way to achieve something like this?
Update: I've managed to fix some of the JS errors, so the page is up and running again. My question remains though: "is there a way of adding a standalone page that is considered standard/best practise, or is it literally just add a separate HTML page at the app root?"
If you use a target='_self' in your linking anchor tag, this should force a full page reload, and that will avoid the angular routing - which is where I expect your request is getting hijacked (by design).
e.g.
link
Answering your updated question
Not to my knowledge, since (as you correctly pointed out) this mixes the SPA design pattern.

How does Angularjs routing work for applications outside the browser?

I am creating a single page app (mobile/desktop) using AngularJS. Based on the limited knowledge I have of AngularJS, I think the routing for the apps/websites is based on urls and $location/$location.path directive is used. However, in mobile or desktop apps, there is no browser. So how does AngularJS routing work in this case if views need to be switched?
Thanks
If you are talking about an Angular application by itself, it will always need something to be interpreted by something. Angular is written in JavaScript which means it will have to be interpreted by something which understands JavaScript. I am using the word interpreted instead of compiled, because JavaScript is not a compiled language.
But then how does something that interprets JavaScript display it on my screen you ask? For this you'll need a bit of background information.
The DOM
This is where we got to the Document Object Model DOM. From W3c:
The Document Object Model is a platform- and language-neutral
interface that will allow programs and scripts to dynamically access
and update the content, structure and style of documents. The document
can be further processed and the results of that processing can be
incorporated back into the presented page. This is an overview of
DOM-related materials here at W3C and around the web.
To dumb the quote above down:
you have a document (web page) which is being displayed and the DOM allows you to change this document which is being displayed.
JavaScript Engine
The link between JavaScript and the DOM is provided by an Engine. Every browser uses a JavaScript Engine. For example Chrome uses the V8 JavaScript engine. From an introduction of V8:
JavaScript is most commonly used for client-side scripting in a
browser, being used to manipulate Document Object Model (DOM) objects
for example. The DOM is not, however, typically provided by the
JavaScript engine but instead by a browser. The same is true of
V8—Google Chrome provides the DOM. V8 does however provide all the
data types, operators, objects and functions specified in the ECMA
standard.
How does this translate to your question?
Everything that wants to display a JavaScript application, needs to have a JavaScript Engine and a DOM. This could be a browser like Chrome, but could also be any other application.
A simple explanation of what a router does, is change the DOM to display different "documents". So plainly said: any application, be it a mobile or desktop application, which has a DOM understands how to use Angular's routing system.
Outside the browser means only application you are speaking about?. angular is tied to HTML pages in general. So its a framework for managing(not exactly appropriate word) the html pages to make them into Single Page Applications so that browser does not need to reload the entire the web application on request of a single page, it helps to invoke the html pages into the main html pages, this makes the application not to reload the entire, but to make available requested pages. this is where the routing comes.
Angular will work just fine there. In fact there is an Ionic project that is based on top of angular. E.g. if you are using Cordova, then the app is rendered inside a browser (or at least with the browser engine). So as far as I know it will behave exactly the same way with the exception of user not being able to type in URL or click back/forward.
Moreover I build an application for browser where I do not user URL as much as possible. E.g. I transition only between states and don't have direct url's in my application at all. Of course I need to support to the extent that a user can type in the url, but the ui-router does that on it's own if you map routes properly. But it seems much more beneficial not to rely on the urls at all for SPA (for internal stuff as you still have the edit url as I said before).

Resources