Help us understand the problem. What is going on with this article?

AMP で任意の JS を実行できる amp-script を試してみた

More than 1 year has passed since last update.

明日の AMP Conf のための事前に動かしてみた。

amp-script とは何か

今まで https://github.com/ampproject/amphtml に登録された一部のJSしか出来なかったAMPだが、amp-script を使うと任意の JS を実行できる。ただし、 WebWorker コンテキストの中でのみ。

本来ならDOMが存在しないWebWorkerだが、しかしDOMに触れないわけではない。 WebWorker の中に DOM と似たようなオブジェクトが実装されており、それを操作することでメインスレッドのJSに反映される。

この DOM がすごい2018: worker-dom - mizchi's blog

https://github.com/ampproject/worker-dom

amp-script を導入する

static/index.html
  <head>
    <!-- ... -->
    <script async src="https://cdn.ampproject.org/v0.js"></script>
    <script
      async
      custom-element="amp-script"
      src="https://cdn.ampproject.org/v0/amp-script-0.1.js"
    ></script>
  </head>
  <body>
    <amp-script layout="container" src="/main.js">
      <button id="hello">Insert Hello World!</button>
    </amp-script>
  </body>
static/main.js
const button = document.getElementById("hello");
button.addEventListener("click", () => {
  const el = document.createElement("h1");
  el.textContent = "Hello World!";
  document.body.appendChild(el);
});

このコードは実際には main-thread で実行されておらず web-worker での実行されている。
ここで具体的にどういうコードを書けるかは https://github.com/ampproject/worker-dom の demo を参照

この例は単純すぎるDOM操作だが、 preact も動くとのこと。 React が動くは不明だが、worker-dom のソースコードを読んだ限り考慮されてはいる。

AMP用 CORS サーバーを立てる

このままではまだ動かない。このコードを AMP として動かすには、AMP用に動くことを証明する Header を付与する必要がある。

CORS in AMP - amp.dev を参考に、雑に node サーバーを立てた。

server.js
const express = require("express");
const app = express();

app.set("port", process.env.PORT || 3000);

app.use((req, res, next) => {
  const host = req.get("host");
  const protocol = host.startsWith("localhost") ? "http" : "https";
  const origin = protocol + "://" + req.get("host");
  res.set("Access-Control-Allow-Origin", origin);
  res.set("AMP-Access-Control-Allow-Source-Origin", origin);
  res.set(
    "Access-Control-Allow-Headers",
    "Origin, X-Requested-With, Content-Type, Accept"
  );
  res.set("Access-Control-Allow-Methods", "GET, POST, OPTIONS, HEAD, PUT");
  res.set("Access-Control-Allow-Credentials", "true");
  next();
});

app.use(express.static(__dirname + "/static"));

app.listen(app.get("port"), function() {
  console.log("Listening on port " + app.get("port"));
});
package.json
{
  "name": "tryamp",
  "version": "1.0.0",
  "main": "index.js",
  "author": "mizchi <miz404@gmail.com>",
  "license": "MIT",
  "scripts": {
    "now-start": "node server.js"
  },
  "dependencies": {
    "express": "^4.16.4"
  }
}

(npm install などは略)

こういう構成を意図してる。

server.js
package.json
static/
  hello.js
  index.html

ローカルで動くのもなんなので now.sh にデプロイ

npm i -g now
now deploy

https://tryamp-ywasobhymt.now.sh/ にデプロイした。

開発者フラグを立てる

(この節は将来的に不要)

まだ動かない。 https://tryamp-ywasobhymt.now.sh/ (または localhost のサーバー) で DevTools を開いて AMP.toggleExperiment('amp-script') を eval する。この状態でリロードするとやっと有効になる

おわり

次は preact + typescript やる

plaid
CXプラットフォーム「KARTE」の開発・運営、EC特化型メディア「Shopping Tribe」の企画・運営、CX特化型メディア「XD(クロスディー)」の企画・運営
https://plaid.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした