こんにちは、さち です。
先日、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回だけになります。
原理的には自分のサイトがフレームで他サイトに読み込まれるのを防ぐ方法と同じですね。
コメント