ユーザスクリプトとは
ユーザスクリプトとは、ブラウザの対象ウェブページでユーザ作成のスクリプトを実行する為の仕組みです。元々は、Firefoxのアドオンとして作成されたGreasemonkey上で使用できるスクリプトでした。その後、後続の拡張機能も同様の仕様で実行可能なユーザスクリプトとして一般化しました。
拡張機能の種類
ユーザスクリプト用の拡張機能として、主に次の3種類が開発されています。
ドキュメント
インストール
- Firefox
- Chrome
- Greasmonkey
- 標準機能としてChrome本体と統合
- ただし、Chromeウェブストア以外からのインストール禁止の余波で、使用不可
- エラーメッセージ「この拡張機能は Chrome Web Storeで提供されていません。知らないうちに追加された可能性があります。」
- Chrome によって無効にされた拡張機能 - Chrome ウェブストア ヘルプ
- Tampermonkey - Chrome ウェブストア
- Violentmonkey - Chrome ウェブストア
- Greasmonkey
- Edge
- Safari
- Tampermonkey on the Mac App Store
- Mac App Store経由の場合、有料($1.99)
- (無料アプリでも)AppStoreの登録料が高額なため、致し方ないことです
- 公式ページから直接ダウンロードする場合、無料
- Tampermonkey • Home
- Mac App Store経由の場合、有料($1.99)
- Tampermonkey on the Mac App Store
ユーザスクリプトの公開と検索
- Greasy Fork
- ユーザースクリプトホスティングサービス
- OpenUserJS
- GitHub / Gist
- GitHubでのユーザスクリプトの検索
デバッグ
ログ出力する
console.log()
関数を使用する- Webコンソール上に出力する
alert()
関数を使用する- ページ上に表示する
GM_log()
関数を使用する- Webコンソール上に出力する
- 使用には、明示的な@grant指定が必要です「
// @grant GM_log
」 - 補足:最新のGreasemonkeyでは既に廃止済みの機能です
エラー出力を確認する
ユーザスクリプトがエラーした場合、Webコンソール上に出力されます。ただし、確実にエラー出力されるとは限りません。
※無言死事例:GreasemonkeyのGM.xmlHttpRequest
関数内のエラー
デバッガーを使用する
- Greasemonkey
- Firefox標準のデバッガーを使用する
- [開発ツール] > [デバッガー] > [ソースファイル] > [user-script://] > [対象ユーザスクリプト]
- Firefox標準のデバッガーを使用する
- Tampermonkey
- ブラウザ標準のデバッガーを使用する
- [Firefox] > [開発ツール] > [デバッガー] > [Tampermonkey] > [userscripts] > [対象ユーザスクリプト]
- [Chrome] > [開発ツール] > [Sources] > [Tampermonkey] > [userscript.html?name=対象ユーザスクリプト]
- スクリプト開始直後にデバッガーを起動する
- [オプション] > [設定] > [全般]
- [設定のモード] を [上級者] に設定する
- [スクリプトをデバッグする] を有効にする
- [オプション] > [設定] > [全般]
- ブラウザ標準のデバッガーを使用する
- Violentmonkey
- ブラウザ標準のデバッガーを使用する
- [Firefox] > [開発ツール] > [デバッガー] > [Violentmonkey] > [対象ユーザスクリプト]
- [Chrome] > [開発ツール] > [Sources] > [Violentmonkey] > [対象ユーザスクリプト]
- ブラウザ標準のデバッガーを使用する
ブラウザ標準デバッガーの使用方法
- ブレークポイント: 行番号をクリック(選択)
- ステップ実行(Play/pause): F8
- 次のブレークポイントまで実行する
- ステップオーバー(Step over): F10
- 次の行まで実行する
- ステップイン{Step in}: F11
- 関数呼び出し以外、次の行まで実行する。関数呼び出し、呼び出した関数へ入る
- ステップアウト(Step out): Shift+F11
- 現在の関数の終端まで実行する
※デバッガの使い方 - 開発ツール | MDN
コードをステップ実行する - 開発ツール | MDN
備考
個人的な提案として初期開発は、Tampermonkey/Violentmonkeyを使用して。最終的にGreasemonkeyに対応させる開発の流れを考えます。
エラー出力の安定性、後方互換性、個別の独自機能など開発面では、Tampermonkey/Violentmonkeyに一日の長があると言えます。ですが、Greasemonkeyは、他と比べて高速であり。また、ユーザ数などでGreasemonkey非対応ともしづらいため、このような流れを考えます。
実行タイミング
ユーザスクリプトの実行タイミングは、@run-at
で指定できます。
@run-at | 概要 |
---|---|
document-start | スクリプトをできるだけ早く実行する(※1) |
document-end | DOMContentLoaded 時に実行する(既定) |
document-idle | DOMContentLoaded 起動後に実行する |
※1: 拡張機能のコンテンツスクリプトは、ウェブページの読み込みより先に実行できます。<head>
を読み込むより早く実行することができます。ただし、WebExtensionAPIにアクセスする場合、非同期処理の影響で最終的に<head>
読み込み中や<head>
より後に実行することになります。そのため、「できるだけ早く実行する」と言う曖昧な表現になります。
別のタイミングで実行する
ページ読み込み時以外でユーザスクリプトを実行したいことがあります。拡張機能のユーザスクリプト実行タイミミングをこれ以上変更することはできませんが、JavaScriptの各種イベントのタイミングで処理を実行することはできます。
ユーザスクリプトで使えそうな主なイベント種類を次に示します。
- クリックしたタイミング
click
イベント- ページ上の既存の要素にイベントを設定することもできます
- 要素そのものをユーザスクリプトで挿入することもできます
- ページ全体のクリックイベントを監視することもできます
window.addEventListener('click', func);
- 要素の状態が変化したタイミング
input/select/change
イベント
- キーボード入力したタイミング
keydown
イベント- ページ独自のショートカットキーを設定することができます
- ジェスチャー操作したタイミング
mousedown/mousemove/mouseup/draggesture
イベント- ページ独自のジェスチャーを設定することができます
- 文字列選択したタイミング
mouseup
イベントwindow.getSelection();
- スクロールしたタイミング
scroll
イベントIntersectionObserver
- 無限スクロールを設定することができます
- DOM要素の変更したタイミング
MutationObserver
- ページを閉じるタイミング
pagehide
イベント- データを保存して、次の訪問時に使用することができます
簡単なバグフィックス・仕様の揺らぎ
@grant
@grant
未指定@grant none
の動作となる
@grant none
と@grant GM
の重複指定@grant none
の動作となるGM
関数は使用できない
@include/@match
@include
,@match
未指定- すべてのサイトにユーザスクリプトを適用する
ページのスクリプト無効時
NoScriptなどを使用してページのスクリプトを無効とした場合、WebWorkerが動作しません。また、FirefoxのTampermonkeyが動作しません。
Greasemonkey(独自)
- Webコンソールにエラー出力しないことがある
Tampermonkey(独自)
- 他と比べて低速
Violentmonkey(独自)
- '@match'で省略されていないポート番号の指定が必要
- 明示的なポート番号の指定が必要
- 逆に明示的にポート番号を指定するとGreasemonkey/Tampermonkeyで動作しない
- ポート番号のありなしを併記することで回避できる
後方互換性の問題
2014年6月~:Greasemonkey2.0
@grant none
がデフォルト設定になるGM_
の関数が@grant
指定なしで使用不可になる
- ユーザスクリプトの実行がウェブページのJavaScriptから分離される
- ユーザスクリプト→ウェブページは、unsafeWindowでアクセスが可能
- ウェブページ→ユーザスクリプトは、アクセス不可
- ただし、cloneInto(), exportFunction(), createObjectIn()を使用すれば可能
※詳細:Greasespot: Greasemonkey 2.0 Release
2017年9月~:Greasemonkey4.0 WebExtension対応
GM_
関数の廃止GM.
関数への移行GM_
とGM.
では関数の仕様が一部異なります- 同期関数だったものが、非同期関数へ移行しています
GM_log()
関数の廃止- 代替:
console.log()
- 代替:
GM_addStyle()
関数の完全な廃止GM_registerMenuCommand()
関数の完全な廃止GM_getResourceText()
関数の完全な廃止
ブックマークレット
ユーザスクリプトと類似するユーザ作成のスクリプトを実行する為の仕組みとして、ブックマークレットがあります。ユーザスクリプトと比べた場合のブックマークレトの利点と欠点を次に示します。
ブックマークレットの利点
ブックマークレットは、拡張機能なしで実行できます。拡張機能を利用できないIEなどの古いブラウザ環境で動作します。また、拡張機能が提供されていないモバイル環境でも動作できます。
ブックマークレットは、ブックマークの選択時に実行できます。これは、GUIとしてとてもわかり易い実行タイミングです。ユーザスクリプトでこれと同様の動作を実行することはできません。
ブックマークレットの欠点
ブックマークレットは、CSP (Content-Security-Policy) 問題に対して無力です。CSPが設定されたページでは、ブックマークレットを起動できなくなります。
ブックマークレットは、CROS (Cross-Origin Resource Sharing) 問題に対して無力です。ブックマークレットでは、外部リソースのAccess-Control-Allow-Originしだいでダウンロードができません。ユーザスクリプトであれば、GM.xmlHttpRequest
関数を使用することでこの問題を回避できます。
ブックマークレットは、ページのスクリプト無効環境に対して無力です。NoScriptなどを利用してスクリプトを無効化した環境でブックマークレットは、動作できません。
備考
ユーザスクリプトの名称
ユーザスクリプトの名称は、「スクリプト名.user.js
」です。
※@name
の名称に「.user.js
」は付けない。
※userChrome.jsの「スクリプト名.uc.js
」と混同してはいけない。
※@name
は、@name:ja
/@name:en
と言語毎に個別で指定できる。
無形関数で囲む
無形関数で囲むの例(function() {
// コード
})();
旧バージョンのGreasemonkeyは、ユーザスクリプトを対象ページに直接書き込むことで、ユーザスクリプトの機能を実現していました。そのため、対象ページ本来のスクリプトと不用意に干渉しないよう無名関数で囲むことが一般的です。
ですが、現在のGreasemonkeyは、ユーザスクリプトを対象ページ本来のスクリプトとは隔離された環境で実行しています。そのため、無名関数で囲まなかったとしても特段問題が発生することはありません。
UserCSS
ユーザースクリプトと同様にユーザースタイルも存在します。スクリプトによる動的処理が不要で、CSS的な静的処理だけで問題を解決できる場合、特に有用です。
使用例として、次のようなものが考えられます。
- 特定要素を目立たせる
- 特定要素を非表示にする
- ダークモード対応する
- etc