Lighthouseをよりパワフルで便利にする

普段、Chromeブラウザで使っているLighthouseですが、Pluginでカスタマイズしたり、
他のツールと併用することでよりパワフルになります :muscle:

でわ、早速試してみましょう :grin:

## Lighthouseとは

> Lighthouse はオープンソースの自動化されたツールでウェブアプリの品質向上に役立ちます。 このツールは Chrome 拡張機能として実行するか、コマンドラインから実行できます。 Lighthouse に監査したい URL を指定して実行すると、ページに対する集中的なテストを実行してパフォーマンスに関するレポートを生成できます。 今後は弱点を検出するテストを利用して、アプリの品質改善の指針を得られるようになります。

参考: https://developers.google.com/web/tools/lighthouse/?hl=ja

## ChromeのDevToolsで実行する

LighthouseはChromeのDevToolsに統合されているので、DevToolsのAuditsタブから実行できます

![ligthhouse-screen.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6470/081c9879-8f09-43b9-0144-01248f7b810c.png)

ちゃんと改善すべき箇所も教えてくれます :+1:

## Command Line Interfaceから実行する

次はCLIで実行してみましょう

packageをインストールします

```
$ npm init -y
$ npm install lighthouse
```

実行してみましょう

```
$ npx lighthouse http://localhost:3000 --view
```

`--view` オプションをつけると、実行結果を表示できますー :relaxed:

ブラウザが起動して、結果が表示されました :smile: 

![ligthhouse-screen-mobile.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6470/7fe6311a-a36c-7a74-a325-a5be6a94535e.png)

ターゲットデバイスのデフォルトが `mobile` なので、その結果が出力されています :+1:

ヘッドレスモードで起動できるオプションがあるので、CI上でも実行できますねー :smile: 

オプション一覧: https://github.com/GoogleChrome/lighthouse#cli-options

### Lighthouseの設定をカスタマイズする

ブラウザでは設定をポチポチと変更できますが、CLIではconfigを指定して実行することができます

SEOのみチェックするように設定してみましょう

```custom-config.js
module.exports = {
  extends: "lighthouse:default",
  settings: {
    onlyCategories: ["seo"]
  }
};
```

参考: https://github.com/GoogleChrome/lighthouse/blob/master/docs/configuration.md

実行してみましょう

```
$ npx lighthouse http://localhost:3000 --config-path=./custom-config.js --view
```

![ligthhouse-screen-seo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6470/56b58367-c0ec-5e4e-a331-1d5119e3e402.png)

SEOのみチェックすることができてますね :+1:

### サイト内のリンク切れをPluginでチェックする

lighthouse使ってるけど、自分のサイト固有のもをチェックしたいときは？ :thinking: 

そう、lighthouseは自分でpluginを作成して、拡張することが可能です :flushed:

早速、プラグインを作成してみましょう :smile: 

ドキュメントを眺めながら下記のファイルを修正、作成していきます :dash: 

```diff
// package.json
{ 
-  "name": "app",
+  "name": "lighthouse-plugin-example",
  "private": true,
- "main": "index.js",
+ "main": "./plugin.js",
  "peerDependencies": {
    "lighthouse": "^5.6.0"
  },
  "devDependencies": {
    "lighthouse": "^5.6.0"
  },
  "dependencies": {}
}
```

```plugin.js
'use strict';

module.exports = {
  audits: [{
    path: "lighthouse-plugin-example/audits/broken-link.js",
  }],
  category: {
    title: 'Broken links',
    description: 'Results for our new plugin category.',
    auditRefs: [
      {id: 'broken-link', weight: 1},
      {id: 'meta-description', weight: 1},
    ],
  },
};
```

```
$ mkdir audits
```

```audits/broken-link.js
"use strict";

const { Audit, NetworkRecords } = require("lighthouse");

const allowedTypes = new Set([
  "font",
  "image",
  "script",
  "serviceworker",
  "style",
  "worker"
]);

class BrokenLinkAudit extends Audit {
  static get meta() {
    return {
      id: "broken-link",
      title: "Link must not be broken.",
      failureTitle: "Have some broken links.",
      description: "Link must not be broken.",
      requiredArtifacts: ["LinkElements", "devtoolsLogs"]
    };
  }

  static async audit(artifacts, context) {
    const links = artifacts.LinkElements.map(e => e.href);

    const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];

    const requests = await NetworkRecords.request(devtoolsLog, context);

    const badRequests = requests.filter(request => {
      const isTargetUrl = links.includes(request.url);
      if (isTargetUrl) {
        return request.statusCode !== 200;
      } else {
        return false;
      }
    });

    const passed = badRequests.length === 0;

    return {
      score: passed ? 1 : 0,
      displayValue: `Found ${badRequests.length} broken links.`
    };
  }
}

module.exports = BrokenLinkAudit;
```

ポイントはNetworkRecordsでリクエスト結果をチェックしてるところですかねー

Lighthouseは実行時に、すべてのリクエストをdevtoolsLogsに格納してくれています！

なので、そのログから対象のurlへのアクセスをfilterして、statusをチェックすればOKというわけです :smile: 

次に、このpluginをインストールしなければなりません :thinking: 

Registryにpushしてもいいのですが、まずはお試しなので `npm link` を使ってこのpackageをインストールしましょう

```
$ npm link
$ npm link lighthouse-plugin-example
```

ひとつめのコマンドは、npmのglobalパスへシンボリックリンクを作成します

ふたつめのコマンドで、currentパスへシンボリックリンクを作成します

```
➜  lighthouse_plugin ls node_modules | grep lighthouse-plugin-example
lighthouse-plugin-example
```

できてますねー :smile: 

では、実行してみましょう

```
$ npx lighthouse https://example.com --plugins=lighthouse-plugin-example --view
```

![ligthhouse-screen-plugin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6470/b5b55df2-f186-153e-b7ab-73e1532b91a4.png)

やった！作成したPluginが追加されていますねー :thumbsup: 

参考:

  - プラグインのドキュメント: https://github.com/GoogleChrome/lighthouse/blob/master/docs/plugins.md
  - 利用できるrequiredArtifacts: https://github.com/GoogleChrome/lighthouse/blob/master/docs/plugins.md#available-artifacts

## まとめ

Lighthouseはpluginの作成など一歩進んだ使い方でよりパワフルで便利になりますねー
[Lighthouseのドキュメント](https://github.com/GoogleChrome/lighthouse/tree/master/docs)にいろいろな使い方が紹介されているのでみてください

Enjoy Lighthouse ヘ(^o^)ノ