To change the first impression is very difficult. And I'm not just talking about people. Technologies also often become hostages of the first impression - their first version. And then, despite the years of development, new opportunities and the elimination of old deficiencies, in the mass consciousness the technology remains the very imperfect, its first version. Those who are not trying to deal with this kind of cognitive distortion can only look at the success of competitors using familiar technologies in new scenarios, with the dumb question: “Well, was it possible !?”.
The most striking example of technology that has gone far ahead compared with what it was at the very beginning, in my opinion is AMP - Accelerated Mobile Pages. Many developers see AMP as a way to put static content of their site (articles, news, notes, etc.) into the Google cache, so that when they open from search, this content is loaded instantly (the high speed of loading AMP pages is indicated by the lightning icon in the search results: )). Naturally, if you need to achieve just such a result, then with AMP it will be very easy to do this. But AMP is much more than just technology for working with static content or Google cache. AMP has long been used as a general-purpose library based on web components to create fast dynamic pages and even entire sites that users get from both search and from other sources, including direct visits. From this point of view, AMP can be ranked with Polymer, React or Angular. Naturally, with an eye to the fact that AMP is designed for simple (so that it doesn’t mean) sites, where the main focus is on content, and the dynamic component is limited.
Separately, I would like to note that despite the name - Accelerated Mobile Pages, AMP can be used to create any sites, both desktop and mobile. The project site - ampproject.org is a great example of what can be done with AMP for a desktop.
In this article, we will look at AMP technology itself, talk about its capabilities and limitations, and also make AMP landing pages for an online store with support for loading, displaying, filtering, and searching for products. This example was not chosen by chance, because e-commerce is the second most popular area after news sites, where AMP is most actively used.
You can see the finished landing page on the gifs above.
AMP is devoted to many articles, among which can be found very critical. Basically, these articles concentrate on one side of the AMP technology, namely the cache. After all, if the site page is put in the cache, and then when you click from the search do not open directly, then this inevitably imposes restrictions. Users seem to bypass your site. The sacramental question arises: who benefits? It may be more profitable to always give content directly? Judging by the fact that AMP is actively used by content publishers, most of them are precisely profitable to use the cache - their sites from the search open instantly. The main problem of the cache is that in the address bar of the browser the user sees not the address of the site on which the AMP pages are placed, for example www.vedomosti.ru , but the address in the cache, in this case it will be like this: www.google.com/ amp / s / www.vedomosti.ru .
This behavior is not a malicious way to divert users from your site. It is rather a technical problem that could not be solved in another way. AMP developers are actively working on solving this problem. This will help the new Web Packaging standard. Thanks to him, the data when loaded into the cache is signed by the certificate of the source domain, and as a result, when displaying AMP pages from the cache, the initial domain will be displayed in the address bar, not the address in the cache.
On the other hand, the problem with the cache, if relevant, is primarily for content publishers. If the main asset is articles or news, then for any publisher it is important how and to whom they are shown. And the fact that publishers were initially wary of AMP is understandable. From here and many disputes on this subject. On the other hand, e-commerce is a completely different job scenario. For the owner of an online store, a concert ticket ticket website, a bank accepting applications for issuing credit cards, or a beauty salon recording clients, it is first and foremost important that customers come and buy. Important conversion. And if there is a technology that will help to make websites faster, increasing conversion due to this, then it will naturally be beneficial to use such technology.
What makes websites fast? You make them fast developers! There is no magic, fast sites are fast because their developers care about performance and work to make sites better. There is a set of best practices and tricks that allow you to create websites that load quickly and also work quickly. For example, it is better to upload heavy images only at the moment when the user scrolls to them, and not immediately when opening the page. It is also worth limiting the total number of loaded resources, use asynchronous scripts, etc. The only problem is that all these practices need to be remembered, kept in mind, and constantly monitored for their use. It's complicated. There is always a temptation to do something that will not meet the best practices, but it will be easier to implement.
AMP is a technology that makes it easy to do the right thing (and eventually get a quick website). And to make a site with AMP slow is difficult. This is achieved through a set of constraints, as well as a validator who checks these constraints. If the page is validated, it can be cached. That is, AMP intentionally restricts you - and this is the main idea of ​​this technology, but in return, you have the confidence that you are using the best practices. You do not need to be an expert in optimization in order to get a good result using AMP. Best practices are used by default, and opportunities for errors are minimized.
At the same time, AMP is not some other kind of HTML, it is a regular library, in which there is nothing that would not be available to the creators of other libraries. With AMP, you use plain HTML markup as well as CSS styles. On AMP, you can make a whole site, if it is simple enough (a typical example is all sorts of landing pages), and if the AMP capabilities are not enough, you can always add non-AMP pages.
On the other hand, the optimization applied in AMP can be done without AMP, but this will require a lot of effort and time. In any case, even if for some reason you decided not to use AMP, it makes sense to at least study how this library works and what it does to apply these approaches on your sites. It may seem that the promotion of AMP is the promotion of a specific library, and not the performance of sites as such. But this is not the case: having a productive site is much more important than using one or another library or framework.
Once again, I would like to note that all the restrictions imposed by AMP are not of an ideological nature, but are caused by utilitarian considerations - they allow you to create fast sites. Point. If in the future there is a way, without sacrificing performance, to remove this or that restriction, then it will naturally be lifted.
What limitations does AMP impose? The most important limitation is that pages cannot contain arbitrary javascript code. The only thing for which limited JavaScript can be used is data binding. Also, do not include external JavaScript and CSS files. There are exceptions: this is the AMP library itself, as well as a list of approved components (you can participate in the development of AMP and create your own components). All CSS should be on the page itself, and its volume is limited to 50 kilobytes. In addition, you cannot use part of HTML tags, such as <img />, instead, they use the web components included in the AMP distribution. For example, the <amp-img /> component is used instead of <img />. This is necessary in order for AMP to control the loading of resources. There are also minor restrictions on CSS caused by performance considerations (you cannot use the! Important modifier and not GPU-accelerated animations). Actually that's all. AMP provides a rich set of components, which partly eliminates the impossibility of writing arbitrary JavaScript code. Components include, for example, amp-date-picker , amp-sidebar , amp-user-notification , amp-facebook-like , amp-access , with which you can implement authentication support, and many, many others. And in absolutely extreme cases, when there is no other way out, you can use iframes with non-AMP content.
Before starting work with AMP, I recommend to study the documentation on the project website - ampproject.org . In addition, it is useful to look at the site ampbyexample.com , which contains excellent examples, most of which can be used almost without change in real projects. If you need ready-made templates, they are available on ampstart.com .
Let's create the landing page of an online bicycle store with a list of products, filtering and searching. Our products will be loaded dynamically. For the purposes of training, we will not use ready-made templates, but to make everything from scratch. The project code can be found on GitHub: https://github.com/spugachev/amp-article
The repository contains a backend on Node.js, as well as AMP pages, which are located in the public folder. To run a project, you need to clone the repository and execute the following commands in the project folder (Node.js must be installed).
>> npm install >> npm start
Create a minimal AMP page. Its code is presented below. In the project that you downloaded from GitHub, the main page public / index.html is intentionally left blank, which we will use to write the code.
<!doctype html> <html amp lang="en"> <head> <meta charset="utf-8"> <script async src="https://cdn.ampproject.org/v0.js"></script> <title> </title> <link rel="canonical" href="http://amp-bike-shop.com/index.html"> <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"> <style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript> <style amp-custom> /* */ </style> </head> <body> <h2> AMP !</h2> </body> </html>
The first thing that catches the eye in the example above is that the HTML markup contains an explicit indication that this is an AMP page. This is achieved either by adding a lightning symbol to the html tag (unfortunately the Habr lightning symbol cuts out), or by adding the word "amp" to the same. Without such an indication, the page will not be validated, and will not be added to the Google cache when indexing.
Next, you need to enable the AMP JavaScript library:
<script async src="https://cdn.ampproject.org/v0.js"></script>
You must also specify the canonical address of the page. If there is a non-AMP version of the page, then the address is indicated Otherwise, the address of the AMP page itself is indicated.
<link rel="canonical" href="http://amp-bike-shop.com/index.html">
In addition, you need to add a meta tag to set the scaling, as well as template CSS styles. These styles can not be changed. They are needed so that when the page loads, but before loading the AMP JavaScript library, non-stylized content did not flash on the screen. If the library for some reason does not load, the content will be shown in eight seconds anyway.
Place an image at the top of the page using the amp-image component. Thanks to the setting of the parameter layout = "responsive", the image will be stretched across the entire width of the container.
<amp-img class="hero-img" src="img/hero.jpg" width="320" height="213" layout="responsive"> </amp-img>
Hereinafter I will not give CSS styles, and they can be found in the project repository on GitHub. So...
Run the project and open the main page in the browser. If the parameter # development = 1 is added to the page address, the page will be automatically validated, and information about this will be output to the browser console. For these purposes, you can use an extension for Chrome called AMP Validator .
For example, if instead of <amp-img /> the usual <img /> tag was used, then such a page would not pass validation, which would be indicated by the corresponding message.
Now we have a basic AMP page with a picture to attract attention and the name of the store. Now it's time to download the list of products from the server and display it on the page. The backed project already includes a service that returns a list of products (in this case, bicycles) in JSON format.
GET /api/bikes [ { "id":1, "img":"img/01.jpg", "title":" ", "price":"28500", "available":false }, { "id":2, "img":"img/02.jpg", "title":" ", "price":"14750", "available":true }, { "id":3, "img":"img/03.jpg", "title":" ", "price":"31200", "available":true }, … ]
Since AMP does not allow writing arbitrary JavaScript code, all actions, including data loading, are set in a declarative style. We need to connect to the page several components that will load and display data, and also allow us to use templates. Since these will be standard AMP components, we are allowed to connect them. We will need components:
<script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script> <script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.2.js"></script> <script async custom-element="amp-list" src="https://cdn.ampproject.org/v0/amp-list-0.1.js"></script>
Add the list component to the page:
<amp-list class="offers" height="3720" layout="fixed-height" src="//localhost:3000/api/bikes" items="."> <div placeholder>...</div> <div fallback> .</div> <template type="amp-mustache"> <div class="card" style="height: 340px;"> <amp-img height="200" layout="fixed-height" src="{{img}}" alt="{{title}}-{{price}}"> </amp-img> <hr/> <h2>{{title}}</h2> {{#available}}<p> </p>{{/available}} {{^available}}<p> </p>{{/available}} <p>{{price}} </p> </div> </template> </amp-list>
The component has the src property set, which determines where the data will be taken from (in our case, the GET request will be executed at “// localhost: 3000 / api / bikes”), as well as the items property, which allows you to search for an array of elements for the list inside the JSON response from the server. Since our answer itself is an array, the value of the items property indicates the answer root.
Next, we define a stub that will be shown at the time of loading the data, as well as a stub in case of an error. But the most interesting is, of course, the template of the list elements. The template format is very simple, I think the mustache template syntax does not require additional explanations.
Add the above code, refresh the page and look at the product list displayed on the page. Simple markup and without writing JavaScript code - we completed the data loading and displayed the data on the page (using the list and template).
Each AMP page has a status. It can be viewed as an object with a hierarchy of properties. The page state can be changed in event handlers using the AMP.setState function.
Add a filter that allows you to display only bikes that are available. To do this, place a checkbox on the page, by clicking on which, we will change the state of the page, assigning the variable onlyAvailable value (according to whether the checkbox is selected or not). The name of the variable is arbitrary, it could be called anything. Note that AMP implements its event handling method. You can handle several events at once, and for each event you can have several actions.
<label> <input type="checkbox" on="change:AMP.setState({ onlyAvailable: event.checked })"/> </label>
The data binding mechanism allows the binding of page state variables to property values ​​in HTML markup. In order for the AMP library to make such a binding, the name of the property that should receive the value must be enclosed in square brackets - []. For example, we will add or remove the CSS class 'active' (this is a non-standard class and it is set by us) depending on the value of the variable onlyAvailable.
<label [class]="onlyAvailable? 'active' : ''" >
In development mode (# development = 1), the page state can be displayed on the browser console using the AMP.printState () function;
Now add to the page status list of goods. To do this, we use a separate component amp-state . The component will load data from the same source as the amp-list , but it will not re-download, since AMP controls the data loading and avoids unnecessary requests. In addition, we will add a macro, which, when the value of the variable onlyAvailable changes, will filter the list of products.
<amp-state id="bikes" src="//localhost:3000/api/bikes"> </amp-state> <amp-bind-macro id="filteredBikes" expression="bikes.filter(bike => onlyAvailable ? bike.available : true)"> </amp-bind-macro>
Now use the filtered list as a data source for the amp-list component. To do this, we associate the src property of the component with the filteredBikes macro. And also we will connect property of height of a component with the quantity of elements. This is necessary because the height of the amp-list component will not automatically adjust to the number of elements. In this example, the number 340 is the height of the item card, and 16 is the padding at the top and bottom.
<amp-list class="offers" height="3720" layout="fixed-height" src="//localhost:3000/api/bikes" [src]="filteredBikes()" [height]="(340 + (16*2)) * filteredBikes().length" items=".">
Notice that the explicit data loading by setting the src = "// localhost: 3000 / api / bikes" property remains. You can not clean it. When loading an AMP page for performance reasons, data binding is not automatically performed. It will be executed only after user actions, such as clicking on the checkbox.
Open the resulting page and check that the filtering works correctly.
The implementation of the search is similar to the implementation of filtering. Add a text field, and when entering the test, we will assign the value of the page state variable to the value entered in the field.
<input type="text" placeholder="" id="query" autocomplete="off" on="input-debounced: AMP.setState({ query: event.value })" />
Backend in our project supports search. To perform a product search, add the “q” parameter to the GET query already familiar to us. We will not dwell on the implementation of the server part, but let's see how to make a new request to the server when the page state changes.
Let's perform data binding for the src parameter of the amp-state component, which we have already used to obtain initial data for filtering. If you change the query variable of the page state, a new search query will be executed.
<amp-state id="bikes" src="//localhost:3000/api/bikes" [src]="query ? '//localhost:3000/api/bikes?q=' + query : '//localhost:3000/api/bikes'"> </amp-state>
Everything, now on the page search works. In addition, the new search query will be the source of data for filtering, which will also continue to work correctly. The full body code of the page is presented below.
<body> <amp-img class="hero-img" src="img/hero.jpg" width="320" height="213" layout="responsive"> </amp-img> <div class="content"> <h2> AMP !</h2> <amp-state id="bikes" src="//localhost:3000/api/bikes" [src]= "query ? '//localhost:3000/api/bikes?q=' + query : '//localhost:3000/api/bikes'"> </amp-state> <amp-bind-macro id="filteredBikes" expression="bikes.filter(bike => onlyAvailable ? bike.available : true)"> </amp-bind-macro> <input type="text" placeholder="" id="query" autocomplete="off" on="input-debounced: AMP.setState({ query: event.value })" /> <label [class]="onlyAvailable? 'active' : ''" > <input type="checkbox" on="change:AMP.setState({ onlyAvailable: event.checked })" /> </label> <amp-list class="offers" height="3720" layout="fixed-height" src="//localhost:3000/api/bikes" [src]="filteredBikes()" [height]="(340 + (16*2)) * filteredBikes().length" items="."> <div placeholder>...</div> <div fallback> .</div> <template type="amp-mustache"> <div class="card"> <amp-img height="200" layout="fixed-height" src="{{img}}" alt="{{title}}-{{price}}"> </amp-img> <hr/> <h2>{{title}}</h2> {{#available}} <p> </p>{{/available}} {{^available}} <p> </p>{{/available}} <p>{{price}} </p> </div> </template> </amp-list> </div> </body>
Bottom line: we created an interactive AMP page with support for loading and linking data. Installed and changed the page status, learned how to work with templates, and also respond to user input. As you can see, AMP perfectly allows you to develop interactive dynamic pages, even despite serious limitations in the use of JavaScript. Try to say now that AMP is for static;). We know that AMP can do much more!
When loading AMP pages into the cache and returning them from the cache, Google performs many optimizations. When you give AMP pages from your site directly, then, naturally, no additional optimizations are performed. If you want to speed up the direct return of AMP pages, use the AMP Toolbox library. It also provides middleware for Express, so usually using AMP Toolbox along with Node.js is a matter of adding a few lines of code. At the same time the speed of loading pages increases!
If you do not collect statistics on the use of your site, it is meaningless to make any changes - you will not have a clear picture of whether the changes were positive, negative or neutral. How can you tell if user experience has improved with the introduction of AMP if you have no information about user experience? Therefore, the introduction of analytics is vital.
AMP supports two main components for data collection: amp-pixel for setting simple pixel and amp-analytics for more sophisticated analytics solutions. Also component amp-experiment allows A / B tests on AMP pages.
With the help of amp-analytics you can connect Google Analytics, Yandex Metric and other providers (for example, Baidu Analytics).
Add analytics to the page is very simple. First you need to connect the appropriate library with the component amp-analytics .
<script async custom-element="amp-analytics" src="https://cdn.ampproject.org/v0/amp-analytics-0.1.js"></script>
And then put the component on the page and adjust the settings. For Google Analytics, it will look like this.
<amp-analytics type="googleanalytics"> <script type="application/json"> { "vars": { "account": "UA-XXXXX-Y" }, "triggers": { "trackPageview": { "on": "visible", "request": "pageview" } } } </script> </amp-analytics>
For Yandex Metrics code is very similar.
<amp-analytics type="metrika"> <script type="application/json"> { "vars": { "counterId": "XXXXXX" } } </script> </amp-analytics>
Naturally, these are the most minimal settings. For any analytical solution, you need to specify in the settings exactly what data you want to collect.
When using the amp-analytics component, there is a problem with tracking users on AMP and non-AMP pages. I want the user id everywhere to be the same. From the point of view of analytics, the user who downloaded your page from the Google cache, and then followed the links to your site directly, would be considered the same user. To do this, you must use the Client ID API. For more information on what settings need to be made, see the Google Analytics Help .
In the case of fairly complex sites, as well as already existing sites, it will be difficult to write or even rewrite everything on AMP. Therefore, usually those pages to which users come from external sources (login pages), make AMP pages. They will quickly open both from the cache and directly. But further, when the user clicks on the link on the AMP page, he will go to your main site. And here it is important that the main site when switching from AMP page loaded instantly. Achieve this allows service workers (Service Workers). When you open the AMP page, it must install the service worker for the main site, and the service worker in turn will download and cache the necessary files. Thanks to this, the links on the AMP page will open instantly, since everything or almost everything that is needed to open the next pages will already be in the cache.
To install the service of the worker, the amp-install- serviceworker component is used. It is connected in the same way as all other AMP components.
<script async custom-element="amp-install-serviceworker" src="https://cdn.ampproject.org/v0/amp-install-serviceworker-0.1.js"></script>
An example of its use is presented below.
<amp-install-serviceworker src="/sw.js" data-iframe-src="https://mydomain.com/sw.html" layout="nodisplay"> </amp-install-serviceworker>
If the user enters your site directly, the component will install the service worker specified by the src parameter. But in the case of loading the AMP page from the cache, it will not be able to do this, since installing service workers for other domains is prohibited. Therefore, you need to create a page on the site that will contain the installation code of the service worker. When booting from the cache, amp-install-serviceworker will open the page in the iframe, and the service worker will be installed.
PWA (Progressive Web Apps) is an approach to how to build modern web applications that are close to the native user experience. The heart of PWA is service workers. You can find the opinion that AMP and PWA are to some extent competitors. In fact, they complement each other. PWA concentrates on long and, if possible, regular user interactions. At the same time, AMP concentrates on the first interaction when the user comes from outside. PWA does not improve this aspect in any way - the first interaction. Therefore, many projects use AMP as an entry point that translates the user to PWA. And it is very reasonable. If you do not assume regular, long-term or complex user interactions, then you can do with one AMP.
In this article, we looked at one use of AMP, although in fact there are still many interesting scenarios. For example, AMPHTML ads are a great way to create ads that load quickly. After all, if AMP pages that open instantly contain slow-loading banners, users most likely will not see such ads. Yes, and on ordinary pages - slow loading ads annoying users. Therefore, it is logical to do the advertising itself (advertising creatives) with the help of AMP.
Users consume content differently on the desktop and on mobile devices. For example, when reading from a phone, users drop reading a long article much earlier than when reading from a desktop (have you read so far? :)). Recently, on mobile devices, the stories format has become increasingly popular, and AMP stories are just the way to make such stories quickly and effortlessly.
In addition, a version of AMP for email (AMPHTML for email) is being developed, which will allow you to create beautiful interactive emails using AMP.
Do not forget also that AMP can be used simply as an insert format for content on your site. For example, if you want to display news, articles or product cards in a React or Angular application, you can store them in AMP format, preload and then instantly display in a web application (or even in a native application). It’s not necessary to use AMP for the entire page — AMP content can be small pieces of content.
With the help of AMP, you can create both entire websites and individual pages, banners, stories, and use AMP as a fast and compact format for inserting content.
Sergey Pugachev, Google Developer Developer
Ps. The article is a personal look at AMP and may not coincide with the opinion of Google or the author's employer;)
Source: https://habr.com/ru/post/419589/
All Articles