2
Help us understand the problem. What are the problem?

posted at

updated at

Organization

任意のサイトURLからOGP Metadata を取得する npm package を作った話 - メタグロス(metagros)

こんにちは、普段は学校に通いながら、インターンや趣味でソフトウェア開発をしています。バックエンドやフロントエンド、インフラ領域を主に触っています。
Twitter: @igsr5_ GitHub: @igsr5

先日自分が所属している Slack コミュニティで「weekly で記事あげていったら面白そうじゃない?」みたいな話があがったので自分が第一号として記事を書いていこうと思います。(既に一日遅れていますが、、)

この記事では個人的に作った Node.js + ESM の npm パッケージを紹介していきます。

作ったライブラリ - Metagros


https://pokemon-incandescent.fandom.com/wiki/Metagross

今回自分が開発したのは非常に軽量で依存関係の少ないメタグロスです。このメタグロスは任意のWebサイトのURLを受け取り、OGP Metadata を取得する事ができます。

// ポケモンの技は英語で move らしい
import { getPageOGPMetadata } from "metagros/move/cometPunch.js";

const url = "https://some.com";

const metadata = await getPageOGPMetadata(url);
console.log(metadata);

// output
{
  title: "Site title",
  description: "Site description.This site is OO's HP ...",
  image: "https://images.com/hoge",
  type: "article",
  siteName: undefined,
  url: "https://some.com"
}

OGP(The Open Graph protocol) とは

ライブラリの詳しい説明に入る前に OGP について触れておきます。
下の画像は Slack 上で https://igsr5.dev を投稿した時の画像です。
Screen Shot 2022-03-21 at 11.19.01.png
リンクURLだけでなくタイトル、説明、画像などのコンテンツが表示されているのがわかります。これらのコンテンツを表示させるための仕組みが OGP です。

先ほどのSlack画像の例ではサイトのHTML上で

<head>
  ...
  <meta property="og:title" content="Sora Ichigo の HP サイト" />
</head>

このような meta タグが記述されています。この記述によってリンクURL以外のリッチコンテンツが実現されます。
og:title 以外にも og:description, og:image, twitter:image などがあり現在の Web サイトのほとんどで指定されています。

現状 meta タグからリッチコンテンツを表現するための単一の技術は存在せず、それぞれのサービスが自分たちで実装しています。OGP(The Open Graph protocol)は各サービスがそれらの実装をするときのスキーマを定義したものです。

og:title などの Basic Metadata や og:description などの Optional Metadata が定義されています。これらはあくまで開発者の技術的設計を簡素化、一般化するためのプロトコルであるため、利用側は追加でスキーマを定義することもできます。例えば twitter:image で Twitter にサイトURLを投稿したときの表示画像を指定できます。

ライブラリの使い方

このライブラリはサイトURLを引数に取り、OGP metadataを戻り値として返すシンプルな関数を提供します。

  1. ライブラリのインストール
    $ npm i metagros
    # or
    $ yarn add metagros
    
  2. 関数呼び出し
    import { getPageOGPMetadata } from "metagros/move/cometPunch.js";
    
    const url = "https://some.com";
    // OGP metadata を取得
    const metadata = await getPageOGPMetadata(url);
    

ライブラリの特徴

このライブラリの特徴をいくつか紹介します。

Native ESM Module

このライブラリはモジュールシステムに ESM を採用して実装しました。個人的な開発なので特に真っ当な理由はなく、好奇心でやってみただけです。

やってみた所感としては CommonJS で実装するよりもめんどくさかったのが正直な感想です。
ESM を導入するメリットとして Top Level await や 非同期import、 ブラウザサポートなどの利点がありますが現状の Node.js で扱おうとするとやはり CommonJS との互換性問題で色々と面倒です。Metagros は現在 ESM 対応のみですが今後 Dual Packages(or CJS) への対応も考えようと思います。

面倒だったこと

  • Jest
    • --experimental-vm-module を有効化する必要あり
  • モジュール拡張子問題
    • Native ESM では CJS とは違いモジュールの拡張子を指定する必要がある
    • これに関してはCJSで拡張子を省略できてしまうのが失敗だという声もある
    • ライブラリの利用側で行う拡張子の解決方法が現時点であまり自明ではない

また、ここまで面倒だと文句を並べていますが自分の理解不足の方が要因としては大きいと感じているので勉強しようと思います。

軽量、低依存

Metagros の unpacked Size は 6.17 kB で軽量なパッケージになっています。
また、Metagros が利用する外部パッケージは jsdom/jsdom のみで、残りの実装は全て Node.js 標準パッケージで行なっています。

600族ポケモン

メタグロスは600族ポケモンの中でもエース的な存在です。そして見た目がイカしてます。OGP Metadata の Meta とかけて非常に適当に命名しましたが個人的には意外としっくりきています。
そういえば レジェンズアルセウスではメタグロスは登場しませんね(あんまりポケモン話をしても怒られが発生しそうなのでここで自重します)

Metagros が生まれるまでの背景

自分がなぜこのライブラリを開発したかを軽く話します。

RSS で必要な情報を取得できない時に、サイトごとのメタデータをいい感じに取得したかった

以前 @catnoseさんが OSS として開発している team-blog-hub を触る機会がありました。このツールではチームメンバーのテックブログをRSSで集約してくれます。詳しいツールの紹介は チーム個々人のテックブログをRSSで集約するサイトを作った(Next.js)
を読むのが良いです。

RSS を用いてテックブログを取得、表示しているので一度 Feed URL を登録すれば後は特に意識せずにサイトが更新され、非常に体験が良かったのですがテックブログの種類によっては望んだ Feed URL が用意できない時がありました。例えば会社ブログです。自分の場合、会社ブログが発行する Feed URL は会社全体の記事を配信しているので個人の投稿を取得する事ができませんでした。またそもそも RSS に対応していないメディアもあるかもしれません。

そこでそれらのブログについても表示に含めるために、必要な情報を自分で用意してRSSから取得できるデータを一緒に表示できる実装を追加しました。望むRSSを取得できない場合は記事ごとに毎回登録する、といったイメージです。

この実装でRSS取得ができないブログも表示に含めたいという目的は果たせていますが、ブログ投稿ごとに必要なデータを自分で用意するのもかなり面倒です。そこでサイトURLを登録したら残りのメタデータは自動で取得するような実装を考え、そのためのツールとして Metagros を開発しました。もう少しライブラリ実装を整理できたら実際に自身のポートフォリオに導入するつもりです。

あとがき

今回はサイトURLからOGP Metadata を取得できる npm パッケージを TypeScript + ESM で開発しました。普段フロントエンドの開発を行なっていますが CJS, ESMなどのモジュールシステムへの理解が低かったので実装途中で何回か詰まりました。勉強したいなとは強く思っているのでこのライブラリを CJS 化してみたり、Dual Pacakages 化したりして勉強していこうと思います。


自分はこのブログの冒頭でこんなことを言いました。

先日自分が所属している Slack コミュニティで「weekly で記事あげていったら面白そうじゃない?」みたいな話があがったので自分が第一号として記事を書いていこうと思います。

コミュニティメンバーと話している時に「前の人が次の人のブログテーマを決めると長続きする」みたいな話があがったのでやってみようと思います。

次の人は @kathmandu (Twitter: @Kathmandumandu) でブログテーマは「バックエンド、インフラ領域でできるWebサービスのパフォーマンスチューニング」です!

これから YounGeekメンバーでさまざまな知見を記事にしていくので是非見てください!

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
2
Help us understand the problem. What are the problem?