2020年のブログ最終更新は12/23(水)の予定です

ユーザースクリプトが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('ユーザースクリプト 実行');
})();

「top」は window.top の省略記述で、トップフレームの URL
「self」は window.self の省略記述で、現在のフレームの URL です。
両者が一致しない時は、フレーム内での実行なのでスクリプトを終了します。
これで、スクリプトの実行は(トップフレームでの)1回だけになります。

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

コメント

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