Repository navigation
JS in AMP #13471
Description
Motivation
AMP offers the ability to easily author web pages with good performance and UX characteristics. One of the tradeoffs of AMP has made to guarantee good performance is the restriction on executing custom JS—this avoids the problems of heavy, slow JS but also prevents reasonable JS use cases. Features like amp-bind help but, compared to non-AMP pages, it’s still more difficult for page authors to write dynamic and interactive widgets and often impossible to reuse existing JS code.
Our goal is to allow custom JS to run in a constrained environment for the purpose of building dynamic and interactive UI components. For example, this feature would support rendering a React component as a UI element on an AMP page.
Requirements
- Allow AMP publishers to author custom JS that renders a UI component
- Preserve AMP’s UX invariants of instant-loading and no-page-jumping
- Follow AMP’s design principles i.e. “user experience > developer experience” and “graceful degradation”
- Maintain strong security and privacy characteristics
Proposed design
We propose to allow 3P (custom) JS to run on a web worker that receives user gesture events from the page and sends mutation requests to the page over postMessage. The 3P JS will be run inside a custom-built sandbox and virtual DOM environment in the worker. The “worker DOM” offers DOM mutation APIs like setAttribute() and appendChild(), and forwards these as mutation requests to the page. The page then runs these mutation requests through a sanitizer—for security and to preserve AMP’s UX invariants—and performs these mutations on the real DOM. This functionality will be offered in a new AMP extension: <amp-script>.
To preserve AMP’s instant-loading behavior, <amp-script> will support “ahead-of-time” rendering. Similar to server-side rendering, the HTML markup for the initial render state of the 3P JS will be inlined as children of <amp-script> and hydrated at runtime. This ensures that the latency of creating the web worker and running the 3P JS doesn’t impact time to first contentful paint.
To preserve AMP’s “no-page-jumping” invariant, mutation requests received from the worker will only be honored within a small window after a user gesture.
Proposed syntax:
<script async custom-element="amp-script"
src="https://cdn.ampproject.org/v0/amp-script-0.1.js"></script>
<!-- amp-script supports all defined-size layout types. -->
<amp-script src=”https://pub.com/my_custom_component.js” layout=responsive>
<!-- The children are the “ahead-of-time” render. -->
<div>...</div>
</amp-script>3P JS can be provided either as an <script type=javascript/worker> element or as an https:// source URL. If the URL is specified, the file will be versioned and cached on an AMP Cache (for pages served from Cache). This avoids skew between the AMP page HTML and 3P JS. Similar to AMP’s existing 50KB CSS size constraint, the 3P script will have a reasonable max file size that will be enforced (actual size TBD).

Activity
findar commentedon Feb 13, 2018
Is 3P JS the customized version of Preact mentioned at AMP Conf 2018?
kristoferbaxter commentedon Feb 13, 2018
3P JS is author written script intended to run within the Sandboxed Web Worker and mutate the DOM of the associated
<amp-script>element in the parent page.rektide commentedon Feb 15, 2018
I love the notion of this. And it sounds, fundamentally, like a good top level idea. I think AMP should do this.
But at the same time, this makes me very nervous. How much experience do we have with 3P JS in the field? What other examples of moving UI-interaction work into web-workers do we have?
This is super exciting and super cool, but I'd be terrified & mortified to consider any specific protocol for accomplishing this more than an experimental vessel at this early stage. It seems like there's a huge field of unknowns heading into the technics of this. I'm delighted and happy to see it happening, but I'm not aware of the royal collective we having much experience doing this kind of thing, and I'm concerned that early design decisions could end up being poor matches in the long run. That the protocol will proxy or emulate DOM sounds like a very good, stabilizing, promising thing, one that will permit the underlying protocols to change and evolve over time, and that's great, but this still seems like something I'd want to explore first as a venture, and make fit to update or replace down the road.
INTENT TO IMPLEMENT does a reasonable job reflecting some of the speculative nature of this work, but I wanted to voice by trepidation none the less. Thanks.
Is there any EcmaScript Module support here, or is this a single file, standalone script only?
senthilp commentedon Feb 15, 2018
@choumx The “ahead-of-time” rendering should also be done by the 3P JS author right? Meaning they should put the markup inside
<amp-script>.kristoferbaxter commentedon Feb 15, 2018
@rektide Agree it's a good idea to continue to reinforce the speculative nature of this work. When announced at AMPConf earlier this week, a slide was used to communicate this.
As for module support, the current plan is for author code to be a single standalone script per
amp-scriptelement – it's expected authors will bundle code, using an iife, to be inserted into a crafted scope exposing a DOM like API.kristoferbaxter commentedon Feb 15, 2018
@senthilp – That's correct. One approach we've been brainstorming is a pre-render Node.js driven CLI leveraging the same DOM implementation shipping within the WorkerGlobalScope.
donohoe commentedon Feb 15, 2018
You do understand that this is just another step in the direction of forking the web as-is and making a whole new version?
From a technical perspective this is a very exciting challenge, but the end result is that any company with a web presence must now create a regular HTML page and also create a separate AMP-specific version with increasingly divergent code base.
Basically, everything needs to be built twice. So... where does AMP end and the web begin now? The game appears to be forking the web and re-inventing the web browser.
cramforce commentedon Feb 16, 2018
@donohoe The meta goal here is to make "AMP go out of the way" from being a JS library to more of a set of UX guidelines. With this change developers can use the framework and tooling of their choice (Be it React, Preact, Angular, Vue, or WebPack, Rollup). At that stage, one doesn't need to use "parallel versions with divergent code bases" as one may either use just one version of use the exact same code base for both.
As you say this is a very exciting technical challenge. Lets keep this issue purely focused on that since there is, indeed, a lot of stuff to discuss (And Github has no threading). If you have additional meta comments, please feel free to file a new issue. I will also move further meta-comments or similar to a new issue should they come up here.
ghelapratik commentedon Mar 9, 2018
@donohoe - We built a website using Native AMP HTML. So, we didn't have to build 2 versions of the same site ( Normal Desktop & AMP ). It did work for us. I think that if AMP allows 3P integration, then may be AMP can be a new web standard altogether.
deepshik commentedon Apr 4, 2018
how to add custom js in amp
IOrlandoni commentedon May 19, 2018
@choumx no longer, simple JavaScript commands and operations must come to the amp. because the limited amp is detrimental to the user experience. In very simple in-page applications, for example (math calculation, currency convert, weight converter etc ..), we do the calculation in php with form action-xhr and show the results with json results.
responsive web inches to cm app :
How can I do this in the page without using action-xhr in amphtML?
niutech commentedon May 19, 2018
mchr3k commentedon Jul 25, 2018
Can you comment on whether you intend to allow custom JS within AMPHTML ads?
The AMPHTML ads spec currently restricts AMPHTML ads to contain no custom JS. The only exception is whitelisted MRC-accredited vendors who can include arbitrary JS in a nested iframe.
The AMPHTML ads landing page claims that "These ads are only delivered after being validated, ensuring that they’re free of malware." and "AMPHTML ads need to be validated before they’re served, eliminating the risk of malware." It's unclear how such strong statements could be made if AMPHTML ads were allowed to contain arbitrary JS.
20 remaining items
jaygray0919 commentedon Apr 28, 2019
We can help! if you want external feedback. Here is a link that uses several libraries (which you may not support). Here is a link that we hope you could support. Here is a reference for a pure D3 instance. Note: several are implemented an non-valid AMP pages (we were comparing a native implementation to an iframe implementation)
dreamofabear commentedon May 1, 2019
/cc @patrickkettner
Jouvan commentedon May 27, 2019
Is there any chance to display Ads on AMP Page without hardcoding? Only just using Javascript? Thank you
patrickkettner commentedon May 30, 2019
hi @bloolight! The token needs to be generated by us, the amp team. This is because they end up being included in the chromium binary. As mentioned in the section you quoted, you can sign up for a token using that link (https://bit.ly/amp-script-trial). You will be emailed the token once it is accepted and generated.
cheers!
Jouvan commentedon May 31, 2019
@patrickkettner any update for me, please?
dreamofabear commentedon Sep 10, 2019
Closing now that amp-script is generally available.