Help us understand the problem. What is going on with this article?

ブックマークレットで使う設定値の置き場所をHeadless CMS にしてみたら快適だった

この記事は

久しぶりにブックマークレットです。
Headless CMSというのが面白そうなので、あえて、ブックマークレットで使う方法を考えてみました。積年の悩み事が解決しそうな感じです。

ブックマークレットの悩み事

SaaS系のインターネットサービスを交えて、ちょっと凝ったブックマークレットを作るときに困るのは、APIのキーやパスワードに近いものを何処に書くかということです。センシティブな情報をソースコードに直接書きたくないのですね、編集が面倒だし。
ベストプラクティスを探そうと、過去にこの記事で考察したのですが、いまいち答えは見つかっていません。編集しやすくするための工夫でしたし。

ということで、今日のメインテーマは、「ブックマークレットで使う設定値の置き場をHeadless CMSにしてみよう」、ということですね。

Headless CMSとは

Micro CMSというHeadlessCMSを作っている人が書いた記事があるので、こちらを参照ください。

アプリエンジニアにこそHeadless CMSが必要だと思う話
https://qiita.com/shoma2da/items/23f38e25496d0bb1675f

簡単にいうと、Webデータベース+REST APIという感じでしょうか。テーブル定義もデータ定義もCMSの管理画面でやるけど、データはAPIでとるだけ。ブックマークレット向きですね。

やってみよう

microCMSの準備

https://microcms.io へ行って右上の新規登録から必要事項を入力してアカウントを作ります。
プランにもよりますが、小規模な使い方であれば、無料で使えます。ありがたや。
image.png

アカウントを作ったあとは、microCMSの設定をしていきます
image.png

microCMSでは、アカウントの下にサービスを作り、サービスの下にコンテンツを作るデータ構造になっています。サービス単位でサブドメインが1つ振られ、コンテンツはドメイン下にぶら下がるURL体系です。

こんな感じです
https://service-name.microcms.io/api/v1/contents-name

サブドメインは早いもの勝ちですね。bookmarkletは頂きました。

設定の作成

具体的にデータを作っていきます。

コンテンツの設定

bookmarkletサービスの下にコンテンツを追加します。URLの一部になるAPIのエンドポイントもここで決めます。
image.png

コンテンツの形式を選びます。リスト形式を選択しました。同じスキーマで複数のレコードを作る場合はリスト形式です。
image.png

その後は、コンテンツのスキーマですね。データベースでいえばテーブル定義です。今回は適当に4つのフィールド(カラム)を作りました。
image.png

データ登録

スキーマにデータを作ります。GUIでさくさくっと。入力が終わったら「公開」を押します
image.png

ここ重要
データを作った直後は、コンテンツIDがランダムの文字列になります。これもURLの一部になるので、分かりやすい文字に変えておきます。今回はproductionとしました。
image.png

データ登録をもう繰り返して、staging用のデータを作りました。2行見えてますね。(できればコンテンツIDも見たいですね)
image.png

APIを試す

microCMSにあるAPIのテスターでデータをとってみます。このURLだと、JSONの配列でとれます。コンテンツの中に2件のデータがあるからですね。
image.png

URLの後ろにコンテンツIDを追加してみます。オブジェクト形式でとれました。
image.png

ここまでで、準備完了です。

ブックマークレット側

ブックマークレットの本体は、こんな感じになります。fetchでmicroCMSのAPIを叩いてデータを取り出しています。

micro-cms-bookmarklet.js
// ==ClosureCompiler==
// @output_file_name default.js
// @compilation_level SIMPLE_OPTIMIZATIONS
// @language_out ECMASCRIPT_2017
// ==/ClosureCompiler==
javascript:(
    async function(service, content, apikey, undefined){
        let url = 'https://' + service + '.microcms.io/api/v1/' + content;
        let config = await microcms(url, apikey);

        console.log('microCMS URL=%s', url);
        console.log(config.project_id);
        console.log(config.api_key);
        console.log(config.login_id);
        console.log(config.password);

        //取得した値を使ってプログラムする
        //
        //

        async function microcms(url, api){
            let opt = {
                method: "GET", // *GET, POST, PUT, DELETE, etc.
                mode: "cors", // no-cors, cors, *same-origin
                cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
                headers: {
                    "Content-Type": "application/json; charset=utf-8",
                    "X-API-KEY": api,
                },
            }
            let response = await fetch(url,opt);
            return response.json();
        }
    }
)
//各人ごとに変わる値は、ここに集約
//左から、microCMSのサービスID、APIのID、コンテンツID、APIのキー
('bookmarklet','sample-config/staging', 'microCMSのAPIキー');

実行結果はこんな風になります。ログが出るだけですけど。
image.png

このように書くと、microCMSの接続情報(サービス名やAPIのキー)がスクリプトの呼び出し部分に集中され、URL部分にしか残らなくなります。ブックマークとして保存したあとに、利用者が変更する形ですね。
ブックマークレットの中は、config.xxxの値を使って、他のサービスのAPIを叩くなり、SlackのWebhook呼び出すなり、自由にできますね。コードの中に変数名しか出てこないのでスッキリします。

この方法のメリット

CDNにJSONファイルを置くのと同じじゃん。と言われると同じです。
一番の違いは、スキーマの拡張や値の設定がmicroCMSのGUIでできることですね。設定の変更と配置はエンジニアでなくてもできます。キーに有効期限があり、定期的に変えないといけないサービスのときは、有効に働きそうです。
microCMS付属のアクセス制御が働くのもうれしいです。不正利用などの怪しい状況になった場合、microCMSのAPIキーをリセットすればOKです。大事なデータを置きすぎないように気を付けてください。

コードと設定値の切り離しができることが一番のメリットです。

まとめ

ブックマークレットで使う「できるだけ秘密にしたい情報」をどうやって扱うか、ということを書きました。自分用なのか、グループに配る用なのかによってやり方は変わりますが、いまのところ、一番いい方法見つけた!と思っています。

おまけ

microCMSにコンテンツ(スキーマ)をコピーする機能か、1つのスキーマを環境ごとに使い分ける機能があるといいなぁ。。値が10個超えてくると設定するのが面倒だろうなぁ。

microCMSを作っている人からコメントをいただき、オブジェクト形式の使い方からリスト形式に書き換えました。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away