明日の 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
amp-script を導入する
<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>
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 サーバーを立てた。
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"));
});
{
"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 やる