New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JS in AMP #13471

Open
choumx opened this Issue Feb 13, 2018 · 23 comments

Comments

Projects
None yet
@choumx
Collaborator

choumx commented Feb 13, 2018

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

@findar

This comment has been minimized.

findar commented Feb 13, 2018

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

@kristoferbaxter

This comment has been minimized.

Collaborator

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

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

Collaborator

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

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.

@kristoferbaxter

This comment has been minimized.

Collaborator

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

This comment has been minimized.

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

This comment has been minimized.

Member

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

@ampprojectbot ampprojectbot added this to the Pending Triage milestone Feb 19, 2018

@psdtomanythings

This comment has been minimized.

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

This comment has been minimized.

deepshik commented Apr 4, 2018

how to add custom js in amp

@kopollo

This comment has been minimized.

kopollo commented 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 :

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

@niutech

This comment has been minimized.

niutech commented May 19, 2018

@mchr3k

This comment has been minimized.

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

@cramforce

This comment has been minimized.

Member

cramforce commented Jul 25, 2018

@m1ck43l There are currently no plans to allow JS in AMPHTML ads and I don't see that happening, nor that it is necessary.

@mchr3k

This comment has been minimized.

mchr3k commented Jul 25, 2018

@pdaexample

This comment has been minimized.

pdaexample commented Jul 27, 2018

Hi,

from this topic, any plan for loading custom script and allow us to access "window", "document", "local storage" etc..? why I ask that because lot of our custom tracking system need to access all of them.

@kristoferbaxter

This comment has been minimized.

Collaborator

kristoferbaxter commented Jul 27, 2018

Our current plan is to allow access to document, (potentially window), and other APIs as you would expect.

Access to localStorage is not planned since the storage is not always on the canonical domain of the document.

@AhsanE

This comment has been minimized.

AhsanE commented Aug 23, 2018

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

Any idea how much it is to be expected? 500kb? 1mb?

@cramforce

This comment has been minimized.

Member

cramforce commented Aug 23, 2018

@AhsanE There hasn't been significant discussion on the topic. But smaller than those values. I'd expect this to be around 50-100KB uncompressed.

Significant update on progress on this topic. We just released the WorkerDOM library https://amphtml.wordpress.com/2018/08/21/workerdom/ which we are planning to use to implement the JS in AMP feature.

@jeffwhelpley

This comment has been minimized.

jeffwhelpley commented Oct 31, 2018

Hey, so what is the status of this? Can I experiment with WorkerDOM in AMP today?

@choumx

This comment has been minimized.

Collaborator

choumx commented Oct 31, 2018

It's in active development but still rough around the edges. You can follow along and play with it on a local build here: https://github.com/ampproject/amphtml/tree/master/extensions/amp-script

@jaswrks

This comment has been minimized.

jaswrks commented Nov 20, 2018

This is great news. Is there a ballpark release date? Couple of months, couple of years?

@choumx

This comment has been minimized.

Collaborator

choumx commented Nov 26, 2018

We're hoping for sometime Q2 next year. :)

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