我们使用AMP作为通用库来创建快速动态站点

改变第一印象是非常困难的。 我不仅在谈论人。 技术通常也成为第一印象的人质-第​​一版。 然后,尽管有多年的发展,新的机会和消除了旧的缺点,但在大众意识中,技术仍然是非常不完善的,它的第一版。 那些不打算解决这种认知偏见的人只能用一个愚蠢的问题来思考竞争对手在新场景中使用熟悉的技术的成功:“会发生什么!!”。



在我看来,与一开始相比就领先一步的最引人注目的技术就是AMP-加速移动页面。 许多开发人员将AMP视为将其网站的静态内容(文章,新闻,便笺等)放入Google缓存的一种方式,因此从搜索中打开时,该内容会立即加载(搜索结果中的闪电图标表示AMP页面的加载速度很高: ))。 自然地,如果您需要达到这样的结果,那么使用AMP将会非常容易。 但是AMP不仅仅是处理静态内容或Google缓存的技术。 AMP长期以来一直被用作基于Web组件的通用库,以创建快速动态页面,甚至创建整个网站,用户可以从搜索和其他来源(包括直接访问)中访问这些网站。 从这个角度来看,AMP可以与Polymer,React或Angular媲美。 自然地,考虑到AMP是针对简单(无论意味着什么)的网站而设计的,这一网站的主要重点是内容,而动态组件受到限制。



我还要指出的是,尽管名称为Accelerated Mobile Pages,但AMP可以用于创建任何网站,包括桌面网站和移动网站。 项目网站ampproject.org是AMP在台式机上可以做的一个很好的例子。


在本文中,我们将考虑AMP技术本身,讨论其功能和局限性,并使AMP进入支持加载,显示,过滤和搜索产品的在线商店。 这个例子并非偶然,因为电子商务是仅次于新闻站点(AMP最活跃)的第二大流行区域。


您可以在上方的GIF中看到完成的着陆页。


AMP专着许多文章,您会发现其中非常关键。 这些文章大多数都集中在AMP技术的一侧,即缓存。 毕竟,如果站点的页面被缓存,然后在搜索中单击时没有直接打开它们,那么这必然会施加限制。 用户似乎到处都是您的站点。 一个神圣的问题出现了:谁从中受益? 总是直接提供内容可能更有利可图? 从内容发布者积极使用AMP的事实来看,他们中的大多数绝对肯定会受益于使用缓存-他们的搜索网站会立即打开。 缓存的主要问题在于,用户在浏览器的地址栏中看不到托管AMP页面的网站本身的地址,例如www.vedomosti.ru ,而是缓存中的地址,在这种情况下,它将是这样的: www.google.com/放大器/ s / www.vedomosti.ru


此行为不是使用户离开您的站点的恶意方法。 这是一个技术问题,无法通过其他方式解决。 AMP开发人员正在积极解决此问题。 新的Web打包标准将有所帮助。 多亏了它,当加载到缓存中时,数据由源域的证书签名,因此,当显示来自缓存的AMP页面时,原始域而不是缓存中的地址将显示在地址栏中。


另一方面,缓存问题(如果相关)主要针对内容发布者。 如果主要资产是文章或新闻,那么对于任何发布者来说,如何显示它们以及向谁显示都非常重要。 出版商最初对AMP保持警惕这一事实是可以理解的。 因此,在这个话题上有很多争议。 另一方面,电子商务是完全不同的情况。 对于在线商店的所有者,出售音乐会门票的站点,接受信用卡申请的银行或记录客户的美容院而言,客户来此购买至关重要。 转换很重要。 而且,如果有一项技术可以帮助提高站点速度,从而提高转化率,那么使用该技术当然会有所帮助。


功放


是什么使网站快速运行? 开发人员,它们使您变得很快! 毫无疑问,快速的网站之所以快,是因为他们的开发人员关心性能,并致力于使网站变得更好。 有一系列最佳实践和技巧可用于创建可快速加载并快速运行的网站。 例如,最好只在用户滚动到沉重的图像时才加载沉重的图像,而不是在打开页面时立即加载沉重的图像。 使用异步脚本等来限制下载资源的总数也是值得的。 唯一的问题是,所有这些做法都需要记住,牢记,并不断监视其应用。 这很复杂。 总是有诱惑力去做一些与最佳实践不符,但更容易实现的事情。


AMP是一项技术,通过它可以轻松地做正确的事情(并最终获得一个快速的站点)。 而且很难使使用AMP的网站变慢。 这是通过一组约束以及检查这些约束的验证器来实现的。 如果页面经过验证,则可以对其进行缓存。 也就是说,AMP故意限制了您-这是该技术的主要思想,但作为回报,您可以确信自己正在使用最佳实践。 您无需成为优化专家就可以使用AMP获得良好的结果。 默认情况下,将使用最佳做法,并且将发生错误的可能性降到最低。


同时,AMP并不是其他类型的HTML,它是一个普通的库,其中没有其他库的创建者无法访问的内容。 使用AMP,您可以使用常规的HTML标记以及CSS样式。 如果足够简单,就可以在AMP上建立整个站点(典型的例子是各种登录页面),如果AMP功能不足,则可以随时添加非AMP页面。


另一方面,可以在不使用AMP的情况下完成AMP中使用的优化,但这将需要大量的精力和时间。 无论如何,即使您出于某种原因决定不使用AMP,也至少应研究该库的工作原理以及将这些方法应用于您的站点的作法。 AMP的推广似乎是特定图书馆的推广,而不是站点本身的表现。 但是,事实并非如此:拥有一个高效的网站比使用一个或另一个库或框架更为重要。


再次,我想指出,AMP施加的所有限制都不是意识形态性质的,而是出于功利主义的考虑而产生的-它们使您可以创建快速站点。 重点。 如果将来有一种在不牺牲性能的情况下消除一个或另一个限制的方法,那么它当然会被取消。


AMP的局限性是什么? 最重要的限制是页面不能包含任意JavaScript代码。 您可以使用受限JavaScript的唯一一件事就是数据绑定。 另外,您无法连接外部JavaScript和CSS文件。 也有例外:这是AMP库本身,以及批准的组件列表(您可以参与AMP的开发并创建自己的组件)。 所有CSS都应在页面本身上,并且其大小限制为50 KB。 此外,您不能使用部分HTML标记,例如<img />;相反,它们使用AMP包中包含的Web组件。 例如,使用<amp-img />组件代替<img />。 这是必需的,以便AMP可以控制资源加载。 由于性能方面的考虑,CSS也有一些限制(您不能使用!Important修饰符和非GPU加速的动画)。 其实仅此而已。 AMP提供了丰富的组件集,部分消除了无法编写任意JavaScript代码的情况。 这组组件包括,例如amp-date-pickeramp-sidebaramp-user-notificationamp-facebook-likeamp-access ,您可以使用它们实现身份验证支持,以及许多其他功能。 在非常极端的情况下,如果没有其他出路,则可以使用包含非AMP内容的iframe。


在开始使用AMP之前,建议您研究项目网站ampproject.org上的文档。 另外,查看ampbyexample.com很有用,它包含了出色的示例,其中的大多数示例都可以在不更改实际项目的情况下实际使用。 如果您需要现成的模板,可以在ampstart.com找到它们。



创建AMP登陆


让我们为在线自行车商店创建一个登录页面,其中包含产品列表,过滤和搜索。 我们的产品将动态加载。 出于培训目的,我们不会使用现成的模板,但是会从头开始做所有事情。 该项目代码可以在GitHub上找到: https : //github.com/spugachev/amp-article


该存储库包含Node.js的后端以及位于公共文件夹中的AMP页面。 要启动项目,您需要克隆存储库并在项目文件夹中执行以下命令(必须安装Node.js)。


>> npm install >> npm start 

页面模板


创建一个最小的AMP页面。 其代码如下所示。 在您从GitHub下载的项目中,有意将主页public / index.html留空,我们将使用它来编写代码。


 <!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> 

在上面的示例中,引起您注意的第一件事-HTML标记包含一个明确的指示,表明这是AMP页。 这可以通过在html标记中添加闪电符号(不幸的是,哈伯符号切割了闪电符号),也可以在其中添加单词“ amp”来实现。 如果没有这样的指示,该页面将不会被验证,也不会在建立索引期间添加到Google缓存中。


接下来,您需要连接AMP JavaScript库:


 <script async src="https://cdn.ampproject.org/v0.js"></script> 

您还必须指定页面的规范地址。 如果该页面有非AMP版本,则会显示其地址。 否则,将指示AMP页面本身的地址。


 <link rel="canonical" href="http://amp-bike-shop.com/index.html"> 

另外,您需要添加用于缩放的meta标签以及模板CSS样式。 这些样式无法更改。 需要它们,以便在加载页面时但在加载JavaScript AMP库之前,非风格化内容不会在屏幕上闪烁。 如果由于某种原因无法加载该库,则无论如何将在八秒钟后显示该内容。


使用amp-image组件将图像放在页面顶部。 通过将layout设置为“ response”,图像将被拉伸到容器的整个宽度。


 <amp-img class="hero-img" src="img/hero.jpg" width="320" height="213" layout="responsive"> </amp-img> 

在下文中,我将不提供CSS样式,可以在GitHub上的项目存储库中找到它们。 所以...


运行该项目并在浏览器中打开主页。 如果将参数#development = 1添加到页面地址,该页面将被自动验证,并且有关此信息将显示在浏览器控制台上。 出于相同的目的,您可以使用称为AMP Validator的Chrome扩展程序。


例如,如果使用常规的<img />标记代替<amp-img />,则该页面将无法通过验证,而是会显示相应的消息。



加载和显示数据


现在,我们有了一个基本的AMP页面,上面有一张图片,以引起人们的注意和商店名称。 现在是时候从服务器下载产品列表并将其显示在页面上了。 Backed项目已经包含一个服务,该服务以JSON格式返回商品清单(在本例中为自行车)。


 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 }, … ] 

由于AMP不允许您编写任意的JavaScript代码,因此所有操作(包括加载数据)均以声明式设置。 我们需要将多个组件连接到将加载和显示数据的页面上,并且还允许我们使用模板。 由于这些将是标准AMP组件,因此我们可以连接它们。 我们将需要以下组件:


  • amp-bind支持数据绑定,
  • amp-mustache用于处理髭格式的模板
  • 以及用于处理将加载和显示数据的列表的放大列表
    在页面标题中连接必要的文件:

 <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> 

将列表组件添加到页面:


 <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> 

为组件设置了src属性,该属性确定将从何处获取数据(在本例中,将在“ // localhost:3000 / api / bikes”处执行GET请求),以及items属性,该属性使您可以在JSON响应内搜索列表的元素数组从服务器。 由于答案本身是一个数组,所以items属性的值指示答案的根。


接下来,我们定义一个存根,该存根将在数据加载期间显示,并且在发生错误的情况下存根。 但是,最有趣的当然是列表项模板。 模板的格式非常简单,我认为小胡子模板的语法不需要其他说明。


添加上面的代码,刷新页面,然后查看页面上显示的产品列表。 通过简单的标记,而无需编写JavaScript代码,我们加载了数据并将数据显示在页面上(使用列表和模板)。


资料筛选


每个AMP页面都有一个状态。 可以将其视为具有属性层次结构的对象。 可以使用AMP.setState函数在事件处理程序中更改页面状态。


添加一个过滤器,使您仅显示可用的自行车。 为此,我们将在页面上放置一个复选框,通过单击该复选框,我们将通过为onlyAvailable变量分配值(根据是否选中该复选框)来更改页面的状态。 变量的名称是任意的,可以称为任何名称。 请注意,AMP实现了自己的事件处理方式。 您可以一次处理多个事件,对于每个事件,您可以执行多个操作。


 <label> <input type="checkbox" on="change:AMP.setState({ onlyAvailable: event.checked })"/>    </label> 

数据绑定机制允许您将页面状态变量与HTML标记中的属性值绑定。 为了使AMP库进行这样的绑定,必须在方括号-[]中使用应该接收该值的属性的名称。 例如,我们将根据onlyAvailable变量的值添加或删除CSS类“ active”(这是非标准类,由我们设置)。


 <label [class]="onlyAvailable? 'active' : ''" > 

在开发模式下(#development = 1),可以使用AMP.printState()函数在浏览器控制台上显示页面的状态。



现在,将产品列表添加到页面状态。 为此,我们使用一个单独的放大器状态组件。 该组件将从与amp-list相同的源下载数据,但不会重新加载,因为AMP控制数据的加载并避免不必要的请求。 此外,我们添加了一个宏,该宏在更改变量onlyAvailable的值时将过滤产品列表。


 <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> 

现在,我们将使用过滤后的列表作为amp-list组件的数据源。 为此,我们将组件的src属性与filteredBikes宏关联。 并且还将组件高度的属性与元素数量联系起来。 这是必需的,因为amp-list组件的高度不会自动调整为元素数量。 在此示例中,数字340是产品卡的高度,数字16是上方和下方的凹痕。


 <amp-list class="offers" height="3720" layout="fixed-height" src="//localhost:3000/api/bikes" [src]="filteredBikes()" [height]="(340 + (16*2)) * filteredBikes().length" items="."> 

请注意,通过设置src =“ // localhost:3000 / api / bikes”属性可以显式加载数据。 您无法删除它。 由于性能原因而加载AMP页面时,不会自动执行数据绑定。 只有在用户操作(例如,单击复选框)之后,它才会执行。


打开结果页面,并验证过滤是否正常工作。


搜寻


搜索实现类似于过滤实现。 添加一个文本字段,当进入测试时,我们将为页面的变量查询状态分配在该字段中输入的值。


 <input type="text" placeholder="" id="query" autocomplete="off" on="input-debounced: AMP.setState({ query: event.value })" /> 

我们项目的后端支持搜索。 要搜索产品,您需要在我们已经知道的GET请求中添加“ q”参数。 我们将不讨论服务器端的实现,而是了解在页面状态更改时如何向服务器执行新请求。


我们对amp-state组件的src参数执行数据绑定,我们已经使用它来获取用于过滤的初始数据。 当您更改查询变量页面状态时,将执行新的搜索查询。


 <amp-state id="bikes" src="//localhost:3000/api/bikes" [src]="query ? '//localhost:3000/api/bikes?q=' + query : '//localhost:3000/api/bikes'"> </amp-state> 

就是这样,现在搜索正在页面上进行。 此外,新的搜索查询将成为用于过滤的数据源,它也将继续正常运行。 该页面的完整代码如下所示。



 <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> 

底线:我们创建了一个交互式AMP页面,支持加载和链接数据。 我们完成了安装并更改了页面的状态,学习了如何使用模板,还响应了用户输入。 如您所见,即使JavaScript使用受到严重限制,AMP仍可以轻松开发交互式动态页面。 现在尝试说AMP是静态的;)。 我们知道AMP可以做的更多!


AMP工具箱


将AMP页加载到缓存中并从缓存中发送时,Google会进行许多优化。 当您直接从您的站点放弃AMP页面时,当然,不会执行任何其他优化。 如果要加快AMP页面的直接返回速度,请使用AMP Toolbox库。 它提供了Express中间件,因此通常将AMP Toolbox与Node.js结合使用,只需添加几行代码即可。 同时,页面加载速度提高了!


进一步的步骤


分析工具


如果您不收集有关网站使用情况的统计信息,那么进行任何更改都是没有意义的-您不会清楚知道更改是正面的,负面的还是中性的。 如果您没有关于用户体验的任何信息,如何判断用户体验是否通过AMP的实施得到了改善? 因此,引入分析至关重要。


AMP支持两个主要的数据收集组件:用于设置简单像素的amp- pixel和用于更复杂的分析解决方案的amp-analyticsamp-experiment组件还允许您在AMP页面上进行A / B测试。


使用amp-analytics,您可以连接Google Analytics(分析),Yandex Metrics和其他提供商(例如Baidu Analytics)。


向页面添加分析非常简单。 首先,您需要将适当的库与amp-analytics组件连接。


 <script async custom-element="amp-analytics" src="https://cdn.ampproject.org/v0/amp-analytics-0.1.js"></script> 

然后将组件放在页面上并配置设置。 对于Google Analytics(分析),它看起来像这样。


 <amp-analytics type="googleanalytics"> <script type="application/json"> { "vars": { "account": "UA-XXXXX-Y" }, "triggers": { "trackPageview": { "on": "visible", "request": "pageview" } } } </script> </amp-analytics> 

对于Yandex Metrics,代码非常相似。


 <amp-analytics type="metrika"> <script type="application/json"> { "vars": { "counterId": "XXXXXX" } } </script> </amp-analytics> 

自然,这些是最小设置。 对于任何分析解决方案,您都需要在设置中指定要收集的数据。


使用amp-analytics组件时,在AMP和非AMP页面上跟踪用户存在问题。 我希望每个地方的用户ID都一样。 对于从分析的角度来看,从Google的缓存下载您的页面然后直接单击指向您网站的链接的用户,则被视为同一用户。 为此,请使用客户端ID API。 在Google Analytics(分析)帮助中详细了解需要进行哪些设置。


服务人员和PWA(渐进式Web应用程序)


在非常复杂的站点以及现有站点的情况下,将很难在AMP上编写甚至重写所有内容。 因此,通常用户从外部来源获得的那些页面(登录页面)构成AMP页面。 它们将从缓存和直接快速打开。 但是,当用户单击AMP页面上的链接时,他将被带到您的主站点。 从AMP页面加载时,立即加载主站点非常重要。 这是通过服务工作者机制实现的。 当您打开AMP页面时,它应该为主站点安装工作程序服务,然后该工作程序服务将下载并缓存必要的文件。 因此,指向AMP页面的链接将立即打开,因为打开以下页面所需的全部或几乎所有内容都已在缓存中。


要安装服务人员,请使用amp- install - serviceworker组件。 它的连接方式与所有其他AMP组件相同。


 <script async custom-element="amp-install-serviceworker" src="https://cdn.ampproject.org/v0/amp-install-serviceworker-0.1.js"></script> 

下面提供了其用法的示例。


 <amp-install-serviceworker src="/sw.js" data-iframe-src="https://mydomain.com/sw.html" layout="nodisplay"> </amp-install-serviceworker> 

如果用户直接访问您的站点,则该组件将安装src参数指定的服务工作程序。 但是,在从缓存加载AMP页面的情况下,他将无法执行此操作,因为禁止为其他域安装服务工作者。 因此,您需要在服务工作者安装代码所在的站点上创建一个页面。 从缓存加载时, amp-install-serviceworker将在iframe中打开页面,并安装服务工作程序。


PWA(渐进式Web应用程序)是一种方法,用于基于用户体验构建与本地应用程序接近的现代Web应用程序。 PWA的核心是服务人员。 也许有人会认为AMP和PWA在某种程度上是竞争对手。 实际上,它们是相辅相成的。 PWA专注于与用户的长期互动,并在可能的情况下进行定期互动。 同时,当用户来自外部时,AMP专注于第一次交互。 PWA并没有完全改善这方面-第一次交互。 因此,许多项目使用AMP作为将用户转移到PWA的入口点。 这是非常合理的。 如果不应该进行常规,长时间或复杂的用户交互,则可以使用一个AMP。


结论


在本文中,我们考察了AMP的一种应用,尽管实际上还有许多有趣的场景。 例如,AMPHTML广告是制作可快速加载的广告的好方法。 毕竟,如果将缓慢加载的标语放置在立即打开的AMP页面上,则用户很可能根本不会看到此类广告。 是的,并且在常规页面上-缓慢加载的广告会惹恼用户。 因此,使用AMP来做广告本身(广告创意)是合乎逻辑的。


用户在台式机和移动设备上使用内容的方式有所不同。 例如,从手机阅读时,用户退出阅读长篇文章的时间要比从台式机阅读时早得多(并且您能阅读到这一点吗?:)。 故事(故事)的格式最近在移动设备上变得越来越流行,而AMP故事只是快速制作此类​​故事而无需额外努力的方式。


此外,正在开发用于电子邮件的AMP版本(用于电子邮件的AMPHTML),这将使您能够使用AMP创建精美的交互式电子邮件。


也不要忘记AMP可以简单地用作在您的网站上插入内容的格式。 例如,如果您需要在React或Angular应用程序中显示新闻,文章或产品卡,则可以将它们存储为AMP格式,进行预加载,然后立即在Web应用程序(甚至本机应用程序)中显示它们。 您不必在整个页面上使用AMP-AMP内容也可以是一小段内容。


使用AMP,您可以创建整个网站以及单个页面,横幅,故事,并使用AMP作为插入内容的快速紧凑格式。


Sergey Pugachev,Google开发人员专家
PS。 本文是AMP的个人观察,可能与Google或作者的观点不一致;)

Source: https://habr.com/ru/post/zh-CN419589/


All Articles