STORES Product Blog

こだわりを持ったお商売を支える「STORES」のテクノロジー部門のメンバーによるブログです。

SaaS の引っ越しに伴うリダイレクト Chrome 拡張機能の実装方法

STORES の社内 IT をいい感じにするお仕事をやっている howdy39 です。

元々使っていた SaaS のナレッジを Notion に引っ越すという記事を yubrot 氏が書いてくれました。 product.st.inc

その記事の中に出てきていた

「旧ナレッジデータベース上のページのURLにアクセスしたら、移行先Notionページに自動リダイレクトする」 というChrome拡張を別途用意しました。

という部分ですが、このリダイレクトを行う Chrome 拡張機能の実装をしたので解説していきます。 SaaSの引っ越しに限らず、簡易的にリダイレクトしたいケースはあるかと思うので参考になれば幸いです。

SaaS の引っ越し時にリダイレクトは必要なのか

基本的にリダイレクトは不要である、と考えています。 そもそもエクスポートや API などを用いても URL が取得できないケースがほとんどなのでリダイレクトするのが現実的ではありません。

原則「リダイレクトはやらない」に倒す、でいいと思っていますが、ナレッジとして使っていた SaaS の場合はそうもいきません。 ナレッジが参照できなくなることで業務継続に大きな影響をあたえる可能性があります。そのため、なんらかの手段でリダイレクトを行うのが好ましい、と判断しました。

リダイレクトをどのように行うのがよいのか

旧 SaaS にリダイレクト機能があればそれを使えばいいですし、自前ドメインでアクセスしていたようなサービスであれば、リダイレクト処理をよしなに組み込めばいいでしょう。

しかし世の中の多くの SaaS はリダイレクト機能もなければ自前ドメインも設定できません。

プロキシを用意するなども考えたのですが、今回は簡易的なリダイレクトで十分と判断し、Chrome 拡張機能を提供することにしました。

業務に大きな影響を与える可能性がある方はリダイレクトする Chrome 拡張機能をインストールをしてもらい、多くの方はインストールせずに気づいたタイミングでURLを変えてもらう*1 という形を取りました。

リダイレクト拡張機能の実装

仕組み

chrome.declarativeNetRequest を使ってリダイレクト処理を設定します。

仕組みを超簡単に説明すると、json ファイルにリダイレクト条件を書いておけば Chrome が HTTP リクエストを投げる前にインターセプトしてリクエストを変更してくれる仕組みです。 そのため旧 SaaS を解約したとしてもリダイレクトが可能です。(そもそもアクセスしていないので)

ソースコード

ファイルとしてはシンプルに マニフェストファイルリダイレクトの設定ファイルアイコン画像 の3種類だけです。

JavaScript のコードは不要で、本当に簡単に実装ができます。

manifest.json(拡張機能の設定ファイル)

{
  "manifest_version": 3,
  "name": "chrome-extension-web-redirector",
  "version": "1.1.0304",
  "description": "特定のURLにアクセスした際にリダイレクトします。",
  "icons": {
    "32": "images/icon32.png",
    "64": "images/icon64.png",
    "128": "images/icon128.png"
  },
  "permissions": ["declarativeNetRequest"],
  "declarative_net_request": {
    "rule_resources": [
      {
        "id": "rules-articles",
        "enabled": true,
        "path": "rules-articles.json"
      }
    ]
  },
  "host_permissions": ["https://example.com/posts/*"]
}

rules-articles.json(リダイレクト処理の定義ファイル)

[
  {
    "id": 19272,
    "priority": 5,
    "action": {
      "type": "redirect",
      "redirect": {
        "url": "https://www.notion.so/notiondomain/xxxxxx"
      }
    },
    "condition": {
      "urlFilter": "https://example.com/posts/19272",
      "resourceTypes": [
        "main_frame"
      ]
    }
  }
  //...
]

社内向けの拡張機能の配布

拡張機能はソースコードをそのまま展開も可能ではあるのですが、アップデートが困難になるため Chrome ウェブストアにあげました。

その際に、下記のクラスメソッドさんの記事を参考にし、非公開設定 x 全社員が入っているグループ を使って社内ユーザーであれば誰でもインストールできるようにする形で配布しました。*2

dev.classmethod.jp

拡張機能実装時のポイント

priority プロパティでURLが長い方の優先度を上げる

今回引っ越し元となる SaaS はナレッジの URL に数値を使っており、新しいナレッジはインクリメントして採番されていました。

そのようなケースの場合、https://example.com/posts/19272 のURLを開こうとしたときに https://example.com/posts/1https://example.com/posts/19 の URL が条件にマッチしてしまい、リダイレクト先がズレるという問題が発生しました。*3

そのため、CSV 生成時に桁数を埋め込んでおいて、下記のようなコマンドを作って prority プロパティに桁数を設定することで解決しました。

これにより、このような順で処理されることになります。

  1. https://example.com/posts/19272(priority: 5)
  2. https://example.com/posts/1927(priority: 4)
  3. https://example.com/posts/192(priority: 3)
  4. https://example.com/posts/19(priority: 2)
  5. https://example.com/posts/1(priority: 1)

rules-articles.json 生成コマンド

cat data.csv | tail -n +2 | jq -R 'split(",")' | jq -s '
  map(
    {
      "id": (.[0]|tonumber),
      "priority": (.[1]|tonumber),
      "action": {
        "type": "redirect",
        "redirect": {
          "url": .[3]
        }
      },
      "condition": {
        "urlFilter": .[2],
        "resourceTypes": ["main_frame"]
      }
    }
  )
' > src/rules-articles.json

Chromeウェブストアへの反映は意外と時間がかかる

declarativeNetRequest は権限としてはかなり強いのですが、社内ユーザー限定の公開で、host_permissions も1ドメインだけだし、コード1行も書いてないし、承認処理はサクッとされるでしょう。 と安易に思っていたのですが、長いときは反映までに4日近くかかっていた気がします。 拡張機能の複雑さとは関係なく一定の時間はかかるようですので余裕をもって準備しておきましょう。*4

おわりに

今回 Notion のページが10万を超えていたため、リダイレクトルールのJSONファイルは234万行にもなりました。

Chrome の動作が重くなったりしないか・・?みたいな不安もあったのですが、差を体感できないぐらいの速度で動いており、Chrome すごい…という気持ちになりました。

何らかのリダイレクトが必要なときに本記事が助けになれば幸いです。

*1:同じページ名で Notion に引っ越されているので検索すればすぐ出てきますし、新旧URLのマッピングスプレッドシートも提供しました

*2:クラスメソッドさんの記事ではグループは指定できないと書かれてありましたができました。仕様変更があったのかもしれません。

*3:完全一致ではなく前方一致

*4:ぎりぎりになって実装してあたふたした