AMP strives to provide a consistently good experience to all users across the web by encouraging the use of high-functioning and seamless components that are ready to go out of the box.
Some web experiences require a high amount of customization that go beyond the state binding capabilities of
amp-bind and the dynamic data retrieval and templating functionality of
amp-mustache. For those one-off cases, AMP has created
<amp-script> component registers a Web Worker to run on a separate thread than the main page. The Web Worker is given its own copy of the DOM through
amp-script component sends messages between the Web Worker thread and the main thread, causing any changes the user makes on the main DOM to be echoed on the Web Worker's false DOM. In turn, the Web Worker can then update the false DOM, which is reflected on the main DOM.
<amp-script> is in experimental mode and may break in unpredictable ways.
Custom scripts caching
<amp-script> as a page that doesn't include it.
To keep experiences on AMP pages consistent, limitations exist on
<amp-script> to guarantee a fast loading time and smooth UI.
- Registering event handlers.
- Splitting a TextNode into multiple TextNodes, to allow for frameworks that require it.
The DOM inside
<amp-script> tags should be almost identical before and after initialization.
For example, if starting with the code below:
<text> Hello world </text>
Worker DOM permits minor changes in structure but not content:
For user experience and security reasons,
amp-script enforced DOM manipulation restrictions.
When a user interacts with elements wrapped inside an
<amp-script> components, DOM manipulations must respond quickly. If running a
fetch function, DOM manipulations must be completed within a five second window. If your
amp-script logic is not preforming a fetch, the DOM has less than one second to update the DOM. If a script mutates the DOM outside of the permitted window, it will result in a fatal error and the
amp-script component will terminate the Web Worker. A terminated
<amp-script> component will not run again.
<amp-script> component uses a fixed layout, other than
layout=container, and is sufficiently small, there is no interaction requirement to manipulate the DOM.
As of April 2019, your
<amp-script> component must be at a fixed hight of
300 px or less to meet the unprompted change requirement.
<amp-script> component on that page. If using a library, it must be imported to each individual
<amp-script> component tags, this includes other AMP components. The
<amp-script> component considers
document.body to be the
amp-script element and not the document's
If you were to call
document.body.appendChild(document.createElement('span')) within the
<amp-script>file in the following document:
<body> <p>Hello!</p> <div> <amp-script layout="container" src="customjs.js"> </amp-script> </div> </body>
It will result in this:
<body> <p>Hello!</p> <div> <amp-script layout="container" src="customjs.js"> <span></span> </amp-script> </div> </body>
As of April 2019, all event triggers are allowed. This may change in the future as
<amp-script> is still an experimental component.
Some synchronous methods are disallowed in
<amp-script> and replaced with alternatives, such as
Element.getBoundingClientRect() could not be implemented in a Web Worker, an async alternative to it,
getBoundingClientRectAsync(), is provided.
getBoundingClientRectAsync() returns a
Promise instead of returning the result directly.
View this chart to see WorkerDOM supported APIs.