GreasemonkeyでTweetDeckをスマホアプリ風に使えるようにする

Qiita初投稿です。よろしくお願いします。

## 作ったもの
### MTDeck(MobileTweetDeck)
https://github.com/mkizka/MTDeck

<img src="https://i.imgur.com/xBrApsM.png" width="300" />
<img src="https://i.imgur.com/aFG6fBr.png" width="300" />

使い方はREADMEを参照。

### 追記
`web-ext`を使用してWebExtensionに対応し、Chromeアドオンとしてもリリースしてみました。Kiwiブラウザーをインストールしてアドオンを追加して「ホーム画面に追加」をすると、PWAとしてアプリ化することが出来ます。

https://chrome.google.com/webstore/detail/mtdeck/ednjoleioepmccklimdkcbbchlcjhpij

## 開発までの経緯
「[TJDeck](https://github.com/totoraj930/TJDeck)」というアプリをご存知でしょうか。

TJDeckはTweetDeckを拡張したAndroid向けアプリで、スマートフォンからの閲覧に適したデザインにするというものです。当時ツイッターのUser Streams終了を受けて話題になり、[ITmedia](https://www.itmedia.co.jp/news/articles/1808/29/news046.html)で記事にもなりました。現在も野良アプリとしてapkファイルがダウンロード可能です。

現在ではTweetDeckのアップデートによって[ツイートできない不具合](https://github.com/totoraj930/TJDeck/issues/4)が発生するなど部分的に機能しなくなっています。リポジトリがアーカイブ化され更新も終了しており、今後もアップデートなどは行われないようです。

使えないなら自分で作ればいいじゃないか、ということで今回はTypeScript + Webpackを使って、アプリとしてではなくUserScriptとしてTJDeckもどきを作ってみました。

iOSでの動作確認報告お待ちしています(Android版Firefox + Tempermonkeyで動作確認済み)

## Greasemonkeyにおける開発
さて、Greasemonkey向けUserScriptの開発についての知見をまとめておきます。

### グローバル関数の使用
GreasemonkeyはAPIとしてグローバルな関数を提供します。ドキュメントは[Tempermonkeyのドキュメント](https://www.tampermonkey.net/documentation.php)にまとまっています。

例えばCSSの挿入には`GM_addStyle`が利用できます(使用の際には後述の`@grant`での宣言が必要です)。TypeScriptで使用する場合は型定義が必要です。

```typescript
declare function GM_addStyle(css: string): void;
```

[DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/greasemonkey)リポジトリにもこれらの利用のための型定義ファイルがあるようです。

### ヘッダ情報の記述(webpack-userscript)
Greasemonkey向けUserScriptではスクリプトファイルの先頭にコメントを書くことでバージョン情報などを記述します。

Webpackでは通常ビルドしたJavaScriptコードは一行にまとめられて出力されるため`webpack.BannerPlugin`などを使ってコメントを残す必要があるのですが、探してみたところこれと同じようにファイルの先頭にGreasemonkey向けの書式で設定を出力できる`webpack-userscript`というライブラリがありました。

https://github.com/momocow/webpack-userscript

使用方法はREADMEにわかりやすくまとまっているので、実際に使用した時のコードを載せておきます。

```js
const WebpackUserScript = require('webpack-userscript')

module.exports = {
  // ...
  plugins: [
    new WebpackUserScript({
      headers: (data) => {
        return {
          name: 'MTDeck',
          grant: 'GM_addStyle',
          match: 'https://tweetdeck.twitter.com'
        }
      },
      metajs: false
    })
  ]
}
```
`headers`のそれぞれの項目は前述のAPIドキュメントに記載されている`@name`、 `@grant`、 `@match`に対応しています。

ちなみに`@version`, `@description`などのいくつかの設定は記述がなくても`package.json`から自動で読み込んでくれるようです。

上記の設定で、以下のようにコードが出力されました。

```js:mtdeck.user.js
  
// ==UserScript==
// @name        MTDeck
// @version     1.0.0
// @author      mkizka
// @description TweetDeckをモバイルで見やすくするUserScript
// @homepage    https://github.com/mkizka/mtdeck
// @match       https://tweetdeck.twitter.com
// @grant       GM_addStyle
// ==/UserScript==

// ...
```

### スマホでのデバッグについて
Webpackでの開発の際、`webpack-dev-server`などを用いてブラウザでホットリロードを実現しますが、UserScriptの場合はすでにあるウェブサイト上で動作させることを目的としているため少々事情が異なります。

ホットリロードのやり方は分からなかったので、

1. webpackの`--watch`オプションで自動ビルド
2. `python -m http.server 8000`でスクリプトを配信
3. `{配信する端末のアドレス}:8000/dist/mtdeck.user.js`にアクセスしてTempermonkey内のデータを適宜更新する

という形を取りました。

開発者ツールによるデバッグはChromeが優秀です。`chrome://inspect/#devices`から接続しているモバイル端末内のChromeアプリをデバッグできます。

同じChromiumベースであれば対応しているようで、Kiwiブラウザなどもデバッグできました。

## おわり
以上、Greasemonkey向けUserScriptの開発についてでした。よければMTDeckもぜひ使ってみてください。

TweetDeckは性能の低い端末だとまだまだ重いようなので、今後はその重さの原因になっているところを調査していきたいですね。