ユーザースクリプトが2回実行されてしまう時の解決方法

この記事は約4分で読めます。
記事内に広告が含まれています

操作画面

こんにちは、さち です。

先日、Firefox のアドオン「Tampermonkey」で、とあるサイト用のユーザースクリプトを書いていました。

動作テストをすると、なぜか「ユーザースクリプト」が2回実行される問題が発生。

今回は、この現象の解決方法について書いていきます。

スポンサーリンク

ユーザースクリプトが2回実行される

  1. テスト用のユーザースクリプトを作りました。ユーザースクリプトが実行されるとコンソールにログが表示されます。
    // ==UserScript==
    // @name         Test Userscript
    // @namespace    http://tampermonkey.net/
    // @version      0.1
    // @description  test
    // @author       uminosachi
    // @match        http://example.com/
    // @grant        none
    // ==/UserScript==
    
    (function() {
      console.log('ユーザースクリプト 実行');
    })();

     

  2. Firefox の「コンソール(Ctrl + Shift + K)」で確認してみると、ユーザースクリプトが2回も実行されています
    操作画面

同じユーザースクリプトでも、「Greasemonkey」で動かすと1回しか実行されませんでした。

「Tampermonkey」とは挙動が異なるようです。

解決方法

色々と調べた結果、原因は「iframe」内でもユーザースクリプトが実行されているからでした。スクリプトにおまじないを書いてフレームを無視するようにしましょう。

  1. 9行目のように ==UserScript== 内に @noframes を追記します。
    // ==UserScript==
    // @name         Test Userscript
    // @namespace    http://tampermonkey.net/
    // @version      0.1
    // @description  test
    // @author       uminosachi
    // @match        http://example.com/
    // @grant        none
    // @noframes
    // ==/UserScript==
    
    (function() {
      console.log('ユーザースクリプト 実行');
    })();

     

  2. これで、ユーザースクリプトの実行は1回だけになります。
    操作画面

「Tampermonkey」の場合、問題が発生した「ユーザースクリプト」のエディター画面から「設定」タブを開き、「最上位フレーム(top)のみで実行する」を「はい」にしても同じ効果が得られます。
操作画面

当然、「最上位フレーム(top)のみで実行する」は、自分のブラウザでのみ有効な設定です。配布する予定があるものは、スクリプト内に @noframes を記述しましょう。

多くのユーザースクリプトはフレーム内での実行を想定していないと思うので、「Tampermonkey」のテンプレートに追記しておいても良いかもしれません。

余談 - 自力実装してみる

前述のような用意されているものを使わないで、JavaScript だけで自力実装する場合はこうなります。

// ==UserScript==
// @name         Test Userscript
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  test
// @author       uminosachi
// @match        http://example.com/
// @grant        none
// ==/UserScript==

(function() {
  if(top !== self) return false;
  console.log('ユーザースクリプト 実行');
})();

topwindow.top の省略記述で、トップフレームの URL
selfwindow.self の省略記述で、現在のフレームの URL です。

この両者が一致しない時は、フレーム内での実行なのでスクリプトを終了します。これで、スクリプトの実行は(トップフレームでの)1回だけになります。

原理的には自分のサイトがフレームで他サイトに読み込まれるのを防ぐ方法と同じですね。

コメント

タイトルとURLをコピーしました