amp-toolbox-php
AMP Toolbox for PHP
A collection of AMP tools making it easier to publish and host AMP pages with PHP.
The following tools are part of this library:
AMP Optimizer for PHP
AMP Optimizer is a library for doing server-side optimization to AMP markup by automatically applying AMP performance best practices and enabling AMP server-side-rendering.
Table of Contents (click to expand)
- Conceptual Overview
- Installation
- Basic Usage
- Usage with a DOM Representation
- Working with Errors
- Included Transformers
- Configuring the Transformers
- Creating a Custom Transformer
- Making a Custom Transformer Configurable
- Transformers Requesting External Data
- Adapting the Handling of Remote Requests
Conceptual Overview
The AMP Optimizer is a AmpProjectOptimizerTransformationEngine
object that sets up a pipeline of consecutive AmpProjectOptimizerTransformer
objects. The engine takes unoptimized input in the form of either a HTML markup string or an AmpProjectDomDocument
object and turns it into an optimized HTML markup string.
During the process, errors might occur that make parts of the optimization impossible. These are collected within an AmpProjectOptimizerErrorCollection
object that you can then iterate over to find out more and provide feedback as needed.
Installation
The AMP Optimizer is part of the AMP Toolbox for PHP library that you can pull into your project via the Composer PHP package manager:
composer require ampproject/amp-toolbox
Basic Usage
The following code snippet shows the most basic way of using the AMP Optimizer:
use AmpProjectOptimizerErrorCollection; use AmpProjectOptimizerTransformationEngine; $transformationEngine = new TransformationEngine(); // 1. $errorCollection = new ErrorCollection; // 2. $optimizedHtml = $transformationEngine->optimizeHtml( // 3. $unoptimizedHtml, // 4. $errorCollection // 5. );
- First we instantiate the transformation engine itself.
-
Then we instantiate an
AmpProjectOptimizerErrorCollection
object as we need a “bag” to collect the errors in and pass them around. -
As a final step, we store the result of calling the transformation engine’s
optimizeHtml()
method, which requires… - … the unoptimized input HTML markup as a string and …
- … the empty error collection we’ve already instantiated. After the transformation engine ran, this collection will contain all errors that were encountered during the transformation.
Usage with a DOM Representation
If you already have a DOM representation, there’s no need to save it as HTML first to use it with the transformation engine. The transformation engine accepts an AmpProjectDomDocument
object[^1] directly via its optimizeDom()
method.
If you have a regular PHP built-in DOMDocument
instead, you can turn it into an AmpProjectDomDocument
using AmpProjectDomDocument::fromNode()
.
use AmpProjectDomDocument; use AmpProjectOptimizerErrorCollection; use AmpProjectOptimizerTransformationEngine; if (! $dom instanceof Document) { $dom = Document::fromNode($dom); } $transformationEngine = new TransformationEngine(); $errorCollection = new ErrorCollection; $transformationEngine->optimizeDom($dom, $errorCollection);
Do note that the optimizeDom()
doesn’t have a return value, as it changes the provided AmpProjectDomDocument
in-place.
Working with Errors
The AmpProjectOptimizerErrorCollection
that you pass into the transformation engine’s optimizeHtml()
or optimizeDom()
method should ideally stay empty after the optimization pass.
To check whether errors were found, you can iterate over the collection, which will provide you with 0 or more AmpProjectOptimizerError
objects.
$errorCollection = new ErrorCollection; // Do the transformation here, while passing in the $errorCollection object. foreach ($errorCollection as $error) { printf( "Error code: %snError Message: %sn", $error->getCode(), $error->getMessage() ); }
A quick count of the errors can be done for early returns as needed:
if ($errorCollection->count() > 0) { $this->log('The AMP serverside optimization process produced one or more errors.'); }
You can check whether the collection of errors contains an error with a specific code as well. The current convention is that all errors have their class shortname (the class name without the namespace) as the error code.
if ($errorCollection->has('CannotRemoveBoilerplate')) { $this->log('The boilerplate was not removed by the Optimizer.'); }
Note that this only lets you check whether an error “category” popped up. It can be one or more errors with that same code. If you need a more detailed check, you should iterate over the collection instead.
Included Transformers
Class (short name)
Description
AmpBoilerplate
Transformer that removes AMP boilerplate <style>
and <noscript>
tags in <head>
, keeping only the amp-custom
style tag. It then (re-)inserts the amp-boilerplate
unless the document is marked with the i-amphtml-no-boilerplate
attribute.
AmpRuntimeCss
Transformer adding https://cdn.ampproject.org/v0.css
if server-side-rendering is applied (known by the presence of the <style amp-runtime>
tag). AMP runtime css (v0.css
) will always be inlined as it’ll get automatically updated to the latest version once the AMP runtime has loaded.
AmpStoryCssOptimizer
Enables AMP Story optimizations such as linking to the amp-story-1.0.css
, and server-side rendering of attributes.
AutoExtensions
Transformer that analyzes the HTML source code to identify the required AMP extensions and automatically imports missing AMP extension scripts as well as removes the ones that are unused.
OptimizeHeroImages
Transformer that optimizes image rendering times for hero images by adding preload and serverside-rendered <img>
tags when possible. Viable hero images are <amp-img>
tags, <amp-video>
tags with a poster
attribute as well as <amp-iframe>
and <amp-video-iframe>
tags with a placeholder
attribute. The first viable image that is encountered is used by default, but this behavior can be overridden by adding the data-hero
attribute to a maximum of two images. The preloads only work work images that don’t use srcset
, as that is not supported as a preload in most browsers. The serverside-rendered image will not be created for <amp-video>
tags.
OptimizeViewport
Transformer that normalizes and optimizes the viewport meta tag. By default it will add <meta name="viewport" content="width=device-width">
if viewport is missing, which is the bare minimum that AMP requires.
ReorderHead
Transformer applying the head reordering transformations to the HTML input. ReorderHead
reorders the children of <head>
. Specifically, it orders the <head>
like so:(0) <meta charset>
tag(1) <style amp-runtime>
(inserted by AmpRuntimeCss
)(2) remaining <meta>
tags (those other than <meta charset>
)(3) AMP runtime .js
<script>
tag(4) AMP viewer runtime .js
<script>
(5) <script>
tags that are render delaying(6) <script>
tags for remaining extensions(7) <link>
tag for favicons(8) <link>
tag for resource hints(9) <link rel=stylesheet>
tags before <style amp-custom>
(10) <style amp-custom>
(11) any other tags allowed in <head>
(12) AMP boilerplate (first <style>
boilerplate, then <noscript>
)
RewriteAmpUrls
Transformer that rewrites AMP runtime URLs to decide what version of the runtime to use. This allows you to do such things as switching to the LTS version or disabling ES modules.
ServerSideRendering
Transformer applying the server-side rendering transformations to the HTML input. This does immediately on the server what would normally be done on the client after the runtime was downloaded and executed to process the DOM. As such, it allows for the removal of the boilerplate CSS that hides the page while it has not yet been processed on the client, drastically improving time it takes for the First Contentful Paint (FCP).