beta

AMP Scriptでamp-script-srcのハッシュに対応する

AMP Scriptを使おうとしたところ、amp-script-srcのハッシュがないというエラーが出たので、対応方法をまとめました。

公開日:2020年5月22日

AMP Scriptの読み込みがエラーになる

こちらの記事を参考に、AMP Scriptをテストしてみようとローカルで実行していたら、

<amp-script width="200" height="50" script="test-js" layout="container">
  <button id="hello">Insert Hello World!</button>
</amp-script>
<script id="test-js" type="text/plain" target="amp-script">
  const button = document.getElementById("hello");
  button.addEventListener("click", () => {
    const el = document.createElement("h1");
    el.textContent = "Hello World!";
    document.body.appendChild(el);
  });
</script>

下記のようなエラーログがコンソールに出て、スクリプトが実行できませんでした。

error.js:208 amp-script Script hash not found. amp-script[script="test-js"].js must have "sha384-xvHk-D96CHXcaLJABMCaD-XJYiaeAuP0DKdxFtWCvpaMgDWwqi8SVTv8fnFUxYJl" in meta[name="amp-script-src"]. See https://amp.dev/documentation/components/amp-script/#security-features.​​​

調べてみると、AMP HTMLに直書きしているスクリプト or クロスオリジンのスクリプトの場合、スクリプトの整合性を取るために、ハッシュをmetaで記述する必要があるようです。

amp-script elements that have a script or cross-origin src attribute require a “script hash”. Script hashes are specified in a <meta name="amp-script-src" content="..."> element in the document head.

A console error will be thrown with the expected content value – you can copy/paste from the error to create the appropriate tag.

Load JavaScript from a remote URL

<meta
  name="amp-script-src"
  content="sha384-XXXXXXXXXXX"/>

これをコンソールに表示されてた「sha384-XXXXX」を含めたmeta要素をheadに入れればOKです。

これが面倒なのであれば、普通にスクリプトを別ファイルにしてsrcから読んでしまうのが楽です。

<amp-script width="200" height="50" src="./test.js" layout="container">
  <button id="hello">Insert Hello World!</button>
</amp-script>

実は、これが一番簡単な解決方法かもしれません。クロスオリジンの場合はダメですが。

毎回コンソールをみるのが面倒だったら

このamp-script-srcのハッシュ値は、スクリプトの内容が変更されるたびに変わります。

頻繁に変更しないようなコードならいいのですが、開発中とかに毎回ハッシュを書き換えるのも面倒ですし、変更漏れがあると動かなくなるので、下記のようなスクリプトで動的に変更させます。

const crypto = require('crypto');

function generateCSPHash(script) {
  const hash = crypto.createHash('sha384');
  const data = hash.update(script, 'utf-8');
  return 'sha384-' + data.digest('base64')
    .replace(/=/g, '')
    .replace(/\+/g, '-')
    .replace(/\//g, '_');
}

generateCSPHash(スクリプト内容);

amp-script documentation for inline scripts needs updating