共有先が増えても触らないコードを決める
作成: / 公開: / 内容更新:
執筆:tamito0201 / 掲載・運営:プロマリ
丸い共有ボタンの裏側を掘る連載の第2回。共有先が増えても書き換えないコードを先に決め、共有先の違いを「名札カード」と呼ぶデータファイル(TOML)へ寄せた設計を、架空の共有先を1つ足した差分の実測と図12点でたどります。
もし、分岐で書いていたら
分けた形の良さは、分けなかった形と並べると見えてきます。仮に、共有先ごとの違いを条件分岐で書いていたとしましょう。「xならこのURL、lineならこのURL、hatenaなら……」と、共有先の数だけ段が続く書き方です。ここでは「分岐のはしご」と呼ぶことにします。
分岐のはしごで共有先を1つ足すと、いま動いている段のすぐ隣に、新しい段を差し込むことになります。足すたびに、既存のコードを開いて書き換える。閉じておきたかった場所に、毎回手が入る形です。しかも同じ分岐は、URLを作る場所だけでなく、色やアイコンを選ぶ場所、クリックしたときの動きを決める場所にも現れがちです。1つの追加が、何か所もの分岐に散らばっていきます。
今回の実装には、共有先の名前で処理を切り替える分岐が1つもありません。代わりに、共有先ごとの違いを、すべてデータの側へ寄せました。次は、その寄せた先をのぞいてみます。
共有先は、名札カードで宣言する
共有先は、それぞれが destinations/ フォルダにあるデータファイル1つで表されています。形式は、設定ファイルなどでよく使われる「項目名 = 値」を並べる TOML です。1つのファイルに共有先1つ分の名前・行き先・色などが並ぶ様子が、名前や所属を書いた名札に似ているので、この記事ではこのファイルを「名札カード」と呼びます。Xの名札カードを、アイコンのSVGだけ省いてそのまま載せます。
# X(旧Twitter)のポスト画面。
key = 'x'
label = 'ポスト'
brand_color = '#000000'
action = 'open'
endpoint = 'https://twitter.com/intent/tweet'
icon = '<svg …>…</svg>'
[params]
url = 'url'
text = 'text'
hashtags = 'hashtagsCsv'
via = 'via'並んでいるのは、名前(key)、画面の文言(label)、共有画面のエンドポイント、渡す項目の対応表(params)、アイコン、ブランドの色、クリックでの動作(action)の7つです。どの項目も値を書いてあるだけで、計算も判断もありません。「どうやって作るか」ではなく「何であるか」を書くこの書き方を、宣言的と呼びます。
[params] の読み方も押さえておきましょう。左辺がSNSの受け取るクエリパラメータの名前、右辺が記事から渡す情報の名前です。Xなら、記事のURLを url に、紹介文を text に、タグを hashtags に、アカウント名を via に入れて渡します。名札カードに書いてあるのはこの対応表だけで、URLを組み立てる処理はどこにもありません。共有先は、どこへ何を渡すかを宣言するだけなのです。
URLを組み立てるのは、1か所だけ
では、誰がURLを組み立てているのでしょうか。ブラウザ側の ShareDestination という部品です。名札カードから読み取った宛先と対応表を持ち、記事の情報を受け取って、共有画面のURLを1本作ります。中に持つ値だけで意味が決まる値オブジェクトとして作られていて、作ったあとは中身が書き換わりません。
shareUrl(request: ShareRequest): string {
if (!this.#endpoint) return request.url;
const pairs = Object.entries(this.#params)
.map(([name, field]) => [name, FIELD[field](request)] as const)
.filter(([, value]) => value !== '')
.map(([name, value]) => `${UriEncoder.encode(name)}=${UriEncoder.encode(value)}`);
return this.#endpoint + (pairs.length ? `?${pairs.join('&')}` : '');
}見てほしいのは、この組み立ての中に「xなら」「hatenaなら」が一度も出てこないことです。対応表を上から順に読み、空の値は送らず、RFC 3986の符号化で安全な文字に置き換えてから「&」でつなぐ。XでもはてなブックマークでもLinkedInでも、同じ手順が同じように働きます。違いはデータの側にあり、組み立てる仕組みは1つ。だから共有先が増えても、このファイルは触りません。
共有先のデータは、ブラウザ用の束に焼き込まれる
ここで、ひとつ不思議に思われたかもしれません。名札カードはデータファイルで、URLを組み立てるのはブラウザで動くTypeScriptです。ブラウザは、どうやって名札カードの中身を知るのでしょうか。
答えは、ビルドの時点での受け渡しです。生成器(tools/config.py)が名札カードのファイルを読み込んでカタログにまとめ、ブラウザで動くコードと一緒に、1つのバンドルへ焼き込みます。
実行時のWordPressは、名札カードを読み込みません。このプラグインのWordPress側が受け持つのは、生成した設定を読み、共有欄の要素を出力することです。名札カードは、ブラウザ用の束を作るための設計図です。設計図は1か所にだけ書き、束は機械が作る。この分担のおかげで、共有先の行き先やロゴを手で2回書く場面がありません。











このページ(2ページ目)の感想・質問・設計へのコメント