知らなきゃ絶対損するPCマル秘ワザ
『月,水,金』の週3回更新!(予定)

こんにちは、さち です。
先日、Firefox のアドオン「Tampermonkey」で
とあるサイト用のユーザースクリプトを書いていました。
動作テストをすると
なぜか、ユーザースクリプトが2回実行される問題が発生。
今回は、この現象の解決方法について書いていきます。
ユーザースクリプトが2回実行される
- テスト用のユーザースクリプトを作りました。
ユーザースクリプトが実行されるとコンソールにログが表示されます。// ==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('ユーザースクリプト 実行');
})(); - Firefox の「コンソール(Ctrl + Shift + K)」で確認してみると
ユーザースクリプトが2回も実行されています。
同じユーザースクリプトでも
Greasemonkey で動かすと1回しか実行されませんでした。
Tampermonkey とは挙動が異なるようです。
解決方法
原因は、「iframe」内でもユーザースクリプトが実行されるためでした。スクリプトにおまじないを書いてフレームを無視するようにしましょう。
- 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('ユーザースクリプト 実行');
})(); - これで、ユーザースクリプトの実行は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回だけになります。
原理的には
自分のサイトがフレームで他サイトに読み込まれるのを防ぐ方法と同じですね。

| ホーム |