I would like to create an e-commerce progressive web app with angular 5. How can I use AMP with angular 5 in Google Material Design Lite? If it is not scalable or feasible then what are the other good options?
I presume that you are already familiar with SSR/server-side rendering using Angular Universal, before anything else. Since no custom JavaScript is allowed on AMP.
Having said that, let's talk a bit about AMP standards and restrictions and see what possible issues are when it comes to Angular.
1. How does a website/app implement AMP, in my experience?
Well, you'd practically have 2 versions for each page (the regular version and the AMP version - with strict rules to adhere to).
Let's say you have a video page on my-app.com/video/1234/some-video-slug
. And you want to tell Google that you have an AMP version for this page. You do that by adding the following in the <head>
: <link rel="amphtml" href="my-app.com/video-amp/1234/some-video-slug">
where /video-amp
would be the route that serves the AMP version. All the next points are about what happens on that AMP route/page.
2. You are not allowed to have any external styles
So, no <link rel="stylesheet" href="path-to-some.css">
.
Only a few allowed by AMP (like Font Awesome //maxcdn.bootstrapcdn.com/font-awesome/
or Material Icons/Google Fonts //font.googleapis.com
, so from specific cdns only, definitely NOT hosted on your own server).
What does this mean? Well, when on an AMP route, you need to strip the server-rendered document of all external css references that aren't allowed by AMP and add those that are allowed, if/when needed - like when you need some icons or google fonts. Removing and Adding tags in the document (so, this includes the <head>
section) is possible using the document
and renderer
provided by Angular. But, to me it seemed slow even to only traverse the children nodes of the <head>
section in order to remove any <link>
tag. And I don't think you could do that outside of your Angular app, since you have very little knowledge about what needs to be done on what route.
3. How do you style your app then?
Well the only custom css that AMP allows you to have is inside a <style>
block within the document.
How do you do that? Well, I don't see any other solution other than having a separate build just for some css, which targets the AMP version and has nothing to do with any Angular/Angular CLI workflow, other than maybe compiling/merging the existing css files you already wrote for your components. And somehow, put the generated result in a <style>
block inside the <head>
section, only when on the AMP version.
But keep in mind that those styles aren't necessarily 100% valid css. You might have /deep/
or :host
.
4. You are not allowed to have ANY custom JavaScript.
So, basically your entire Angular app code should not be included. You have to strip the server-rendered html out of any <script>
tags.
5. How do you javascript then, without custom JavaScript?
For example, it would seem crazy to not have a sliding menu or a dropdown menu, on mobile. Well... You can! But only by using AMP "components".
You'd have to use <amp-sidebar>
instead of <mat-sidenav>
or whatever custom component you might have built. But - somehow - only when on the AMP route, because I love Angular Material components.
And how does it work? The <amp-sidebar>
?
Well, when AMP offers you components, that includes JavaScript. In order to make the sidebar work, you can include: https://cdn.ampproject.org/v0/amp-sidebar-0.1.js
. That is allowed. You generally have a lot of common used/needed components available: amp-carousel
, amp-img
(yes, you are not allowed to simply use the <img>
tag), amp-video
, amp-accordion
...
6. What about the rest of the HTML document?
Well, by simply passing a server-rendered html of an Angular app through the AMP validator, there are a lot of problems here also:
It errors on any custom attributes. And Angular is full of those, especially to emulate a native ViewEncapsulation (you've seen all the _ngcontent-c1
and such attributes). In order to get rid of those, I guess you'd either have to go with ViewEncapsulation.None
, but then each component style will become global OR strip the server rendered html out of all those _ng...
attributes and go though a great deal of pain to somehow build an AMP css that only targets by class/id etc. and use more classes in your components to style by anyway.
It also errors on all custom tags (that aren't AMP, of course).
And you know Angular apps and Material Components are build with
those. Even the very first one: <app-root>
. And, honestly, I
wouldn't work with anything else other than tag selectors and, in
some cases attribute selectors (like with Directives).
This is all that I could think of, so far.
I would say that implementing AMP on an Angular app is close to impossible at this point in time.
But, given that AMP and Angular are both Google projects, I would expect to see some progress in regards to Angular+AMP soon enough. I've heard someone saying that Rob Wormald actually mentioned something about AMP early this year, like in April at Ng-Conf... But I couldn't find anything on that, or any progress so far, and we're close to 2018 already. Plus, maybe there were just some ideas, not even a road map... don't know!?
Hopefully, with Angular 6! I'm an optimist.
For now, I think that a progressive web-app should be fast enough that AMP wouldn't be able to improve much on that speed (as long as you're not on a bad connection on the first load). I don't know how you'd rank on that, though (having a really good PWA versus implementing AMP - when it's one or the other, not both)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With