先日Cloudflare Workersでウェブページの本文を抽出したくなったことがありました。本文抽出といえば、@mozilla/readabilityが使えそうです。しかし依存に含まれるnwsapiにはFunction
コンストラクタが多用されており*1、Cloudflare Workersでは動作しません。これを修正するのも大変そうです。
そこで、TinyGoを使用してgo-readabilityをwasmにコンパイルしてみることにしました。
TinyGo のドキュメントUsing WASM | TinyGo のままではCloudflare Workersでは動かなかったので、TinyGoに含まれるwasm_exec.js
を少し修正したり*2、
import側もwasmファイルをfetch
しているのを変更したり*3すると無事動きました。
動作するコードは https://github.com/mechairoi/cloudflare-go-readability-demo
Cloudflareにデプロイするか、ローカルでnpm run devを実行してから、/?url=https://example.com/
のようにアクセスすると、本文がテキストで返ってくるはずです。ビルドサイズは圧縮後約850kBで、Cloudflare Workersのフリープランは1MBなのでセーフですね。golangのwasmはRustと比べるとJavaScriptからの利用に少し癖があるように感じましたが、ちゃんと動いてくれて便利ですね。
おまけ
masukomi/arc90-readability: a copy of the original arc90 repo with links to many of the current ports.によるとReadabilityライブラリには多くの実装があるようです。実は最初はRustで書かれたkumabook/readabilityをwasmにコンパイルして使っていました。 しかし、試しているといくつかのページうまく抽出できないケースがあったり、またmozilla/readabilityをrustで書き直すにkumabook/readabilityの実装はMozilla版と比べると古いという記述もあったので、今回はgo-readabilityを使用することにしました。
*1:Remove use of `Function` constructor · Issue #51 · dperini/nwsapi · GitHub
*2:https://github.com/mechairoi/cloudflare-go-readability-demo/commit/ad44347ba9075f7c6ff2a3de09e3bea4a85aced1
*3:https://github.com/mechairoi/cloudflare-go-readability-demo/blob/24896fa4e73e168722c55acdd868799d7b1cebb0/src/index.ts#L14-L25