Skip to content

JS in AMP #13471

Closed
Closed

Description

@dreamofabear

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

js in amp_ i2i

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

/cc @cramforce @kristoferbaxter

Activity

  1. added
    INTENT TO IMPLEMENTProposes implementation of a significant new feature. https://bit.ly/amp-contribute-code
    on Feb 13, 2018
  2. findar commented on Feb 13, 2018

    @findar

    Is 3P JS the customized version of Preact mentioned at AMP Conf 2018?

  3. kristoferbaxter commented on Feb 13, 2018

    @kristoferbaxter
    Contributor

    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.

  4. rektide commented on Feb 15, 2018

    @rektide

    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?

  5. senthilp commented on Feb 15, 2018

    @senthilp

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

  6. kristoferbaxter commented on Feb 15, 2018

    @kristoferbaxter
    Contributor

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

    screen shot 2018-02-15 at 12 53 48 pm

    As for module support, the current plan is for author code to be a single standalone script per amp-script element – it's expected authors will bundle code, using an iife, to be inserted into a crafted scope exposing a DOM like API.

  7. kristoferbaxter commented on Feb 15, 2018

    @kristoferbaxter
    Contributor

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

  8. donohoe commented on Feb 15, 2018

    @donohoe

    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.

  9. cramforce commented on Feb 16, 2018

    @cramforce
    Member

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

  10. added this to the Pending Triage milestone on Feb 19, 2018
  11. ghelapratik commented on Mar 9, 2018

    @ghelapratik

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

  12. deepshik commented on Apr 4, 2018

    @deepshik

    how to add custom js in amp

  13. IOrlandoni commented on May 19, 2018

    @IOrlandoni

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

    <label>Inches</label>
    <input id="inputInches" type="number" placeholder="Inches" oninput="LengthConverter(this.value)" onchange="LengthConverter(this.value)"> 
    cm: <span id="outputcm"></span> 
    <script>function LengthConverter(valNum) {  document.getElementById("outputcm").innerHTML=valNum/0.39370; } </script>
    

    How can I do this in the page without using action-xhr in amphtML?

  14. niutech commented on May 19, 2018

    @niutech
    Contributor
  15. mchr3k commented on Jul 25, 2018

    @mchr3k

    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.

  16. 20 remaining items

  17. jaygray0919 commented on Apr 28, 2019

    @jaygray0919

    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)

  18. dreamofabear commented on May 1, 2019

    @dreamofabear
    Author
  19. Jouvan commented on May 27, 2019

    @Jouvan

    Is there any chance to display Ads on AMP Page without hardcoding? Only just using Javascript? Thank you

  20. patrickkettner commented on May 30, 2019

    @patrickkettner
    Contributor

    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!

  21. Jouvan commented on May 31, 2019

    @Jouvan

    @patrickkettner any update for me, please?

  22. self-assigned this
    on Jul 9, 2019
  23. dreamofabear commented on Sep 10, 2019

    @dreamofabear
    Author

    Closing now that amp-script is generally available.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    ⌂ Proxy