lighthouseを自動で指定回数動かしてWebパフォーマンスを確認する環境を構築する

# ~~pupeteerで~~lighthouseを自動で指定回数動かしてWebパフォーマンスを確認する環境を構築する

* 改めて整理し、今回はpupeteerは使わなくなりました。

```text:Tree-map
[Homebrew]
├─[formula]
│ ├─npm
│ └─...

[npm]
├─express
├─lighthouse
└─...
```

## プロジェクトを作成する

```sh:Terminal
$ mkdir node_js_api_sample_1
$ cd node_js_api_sample_1/
```


## プロジェクト名やバージョンなどを管理する(NPM init)

* `npm init` を実行したカレントディレクトリに `package.json` が作成される
* [npmをインストールした後最初に使用する初期化処理を意味するコマンド](https://techacademy.jp/magazine/16151)ではなく、プロジェクトの初期化処理

##### 0. npmをインストールしていない場合

* `brew search`

```sh:Terminal
$ brew search npm
==> Formulae
npm                                                                                    pnpm
```
* `brew install`

```sh:Terminal
$ brew install npm
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 3 taps (homebrew/core, homebrew/cask and homebrew/services).
==> New Formulae
mmctl                                                                                  wasmer
==> Updated Formulae
ruby-build ✔       calicoctl          exploitdb          gradle             kapacitor          mill               opam               serverless         typescript
alp                cgrep              faas-cli           grakn              kawa               minetest           openjdk            sile               vtk
angular-cli        cimg               fastlane           groovy             kepubify           minio              pandoc-crossref    skaffold           vulkan-headers
ansible            clojure            flann              gssdp              libbi              mlpack             pcl                sn0int             wabt
armadillo          composer           flow               gupnp              libde265           mongo-c-driver     pdal               snapcraft          whistle
aws-cdk            contentful-cli     flyway             haproxy            libmatio           mono               plantuml           snappy             xmrig
aws-sdk-cpp        csound             frugal             hdf5               libphonenumber     mpd                pspg               solr               youtube-dl
bandwhich          csvq               gcab               hey                libsecret          msitools           purescript         sourcekitten
bibtexconv         deno               gdal               hledger            libsigc++          nco                pyinvoke           spdlog
bison              dependency-check   ghq                jenkins            libtensorflow      ncview             q                  starship
blis               devspace           gitleaks           jfrog-cli-go       libtorch           nebula             qmmp               sxiv
broot              dnscontrol         gmic               jpeg               libxml++3          netcdf             rke                terraform-docs
byobu              ensmallen          gmt                just               lxc                netlify-cli        sbt                terrahub
byteman            ethereum           gmt@5              kakoune            micronaut          okteto             scc                topgrade
==> Deleted Formulae
lastfmfpclient

==> Installing dependencies for node: icu4c
==> Installing node dependency: icu4c
==> Downloading https://homebrew.bintray.com/bottles/icu4c-64.2.mojave.bottle.tar.gz
==> Downloading from https://akamai.bintray.com/e8/e858556120acc0c2d52b8fb572b677856724cc28d24a7e1b2762d458a2977c8e?__gda__=exp=1579541904~hmac=12a35835f00b20d6ff6164725a306
######################################################################## 100.0%
==> Pouring icu4c-64.2.mojave.bottle.tar.gz
==> Caveats
icu4c is keg-only, which means it was not symlinked into /usr/local,
because macOS provides libicucore.dylib (but nothing else).

If you need to have icu4c first in your PATH run:
  echo 'export PATH="/usr/local/opt/icu4c/bin:$PATH"' >> ~/.bash_profile
  echo 'export PATH="/usr/local/opt/icu4c/sbin:$PATH"' >> ~/.bash_profile

For compilers to find icu4c you may need to set:
  export LDFLAGS="-L/usr/local/opt/icu4c/lib"
  export CPPFLAGS="-I/usr/local/opt/icu4c/include"

For pkg-config to find icu4c you may need to set:
  export PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig"

==> Summary
🍺  /usr/local/Cellar/icu4c/64.2: 257 files, 69.2MB
==> Installing node
==> Downloading https://homebrew.bintray.com/bottles/node-13.6.0.mojave.bottle.tar.gz
==> Downloading from https://akamai.bintray.com/bc/bc3727f6f1b1f079b53a19c26c985a066a1525feffa2d2594a5626618f3bac6e?__gda__=exp=1579541924~hmac=f8b1ea89a976b43f537b93024aad8
######################################################################## 100.0%
==> Pouring node-13.6.0.mojave.bottle.tar.gz
==> Caveats
Bash completion has been installed to:
  /usr/local/etc/bash_completion.d
==> Summary
🍺  /usr/local/Cellar/node/13.6.0: 4,663 files, 60MB
==> Caveats
==> icu4c
icu4c is keg-only, which means it was not symlinked into /usr/local,
because macOS provides libicucore.dylib (but nothing else).

If you need to have icu4c first in your PATH run:
  echo 'export PATH="/usr/local/opt/icu4c/bin:$PATH"' >> ~/.bash_profile
  echo 'export PATH="/usr/local/opt/icu4c/sbin:$PATH"' >> ~/.bash_profile

For compilers to find icu4c you may need to set:
  export LDFLAGS="-L/usr/local/opt/icu4c/lib"
  export CPPFLAGS="-I/usr/local/opt/icu4c/include"

For pkg-config to find icu4c you may need to set:
  export PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig"

==> node
Bash completion has been installed to:
  /usr/local/etc/bash_completion.d
```

##### 1. npm init

```sh:Terminal
$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (node_js_api_sample_1) 
version: (1.0.0) 
description: lighthouse on NodeJS on express by WebAPI
entry point: (index.js) 
test command: 
git repository: https://github.com/webmaster-patche/node_js_api_sample_1.git
keywords: lighthouse NodeJS express API
author: webmaster-patche
license: (ISC) 
About to write to /Users/webmaster-patche/node_js_api_sample_1/package.json:

{
  "name": "node_js_api_sample_1",
  "version": "1.0.0",
  "description": "lighthouse on NodeJS on express by WebAPI",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/webmaster-patche/node_js_api_sample_1.git"
  },
  "keywords": [
    "lighthouse",
    "NodeJS",
    "express",
    "API"
  ],
  "author": "webmaster-patche",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/webmaster-patche/node_js_api_sample_1/issues"
  },
  "homepage": "https://github.com/webmaster-patche/node_js_api_sample_1#readme"
}


Is this OK? (yes) yes
```

```sh:Terminal
$ ls
package.json
```


## expressをインストールする

##### 1. npmでインストールする（package.json追記タイプ）

* `--save` オプションを指定するので、カレントディレクトリに指定のパッケージをインストールするときに package.json の dependencies欄 にパッケージ名が記録される

```sh:Terminal
$ npm install --save express
npm notice created a lockfile as package-lock.json. You should commit this file.
+ express@4.17.1
added 50 packages from 37 contributors and audited 126 packages in 10.244s
found 0 vulnerabilities

```

##### 2. package.jsonの依存関係を確認する

```sh:Terminal
$ cat package.json
{
  "name": "node_js_api_sample_1",
  "version": "1.0.0",
  "description": "lighthouse on NodeJS on express by WebAPI",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/webmaster-patche/node_js_api_sample_1.git"
  },
  "keywords": [
    "lighthouse",
    "NodeJS",
    "express",
    "API"
  ],
  "author": "webmaster-patche",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/webmaster-patche/node_js_api_sample_1/issues"
  },
  "homepage": "https://github.com/webmaster-patche/node_js_api_sample_1#readme",
  "dependencies": {
    "express": "^4.17.1"
  }
}
```

## 先ずはHello worldを用意

* expressを使用してlocalhost:8081アクセスで `Hello world` を返すアプリを用意する

```javascript:index.js
// expressモジュールを読み込む
const express = require('express');

// expressアプリを生成する
const app = express();

// ルート（http://localhost/）にアクセスしてきたときに「Hello world」を返す
app.get('/', (req, res) => res.send('Hello world'));

// ポート8081でサーバを立てる
app.listen(8081, () => console.log('Listening on port 8081'));
```

## Web-apサーバ起動

```sh:Terminal
$ node index.js
Listening on port 8081
```

* `http://127.0.0.1:8081/` にアクセスする

![スクリーンショット 2020-01-21 2.38.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179927/f4743784-9353-7e69-146c-47c786f5b3b8.png)


* `Hello world` が表示されました

* 停止する場合は `Ctrl + C` でシグナルを送信します


## pupeteerをインストールする

##### 1. npmでインストールする（package.json追記タイプ）

```sh:Terminal
$ npm install --save puppeteer

> puppeteer@2.0.0 install /Users/webmaster-patche/node_js_api_sample_1/node_modules/puppeteer
> node install.js

Downloading Chromium r706915 - 111.8 Mb [====================] 100% 0.0s 
Chromium downloaded to /Users/webmaster-patche/node_js_api_sample_1/node_modules/puppeteer/.local-chromium/mac-706915
+ puppeteer@2.0.0
added 40 packages from 21 contributors and audited 176 packages in 32.736s

1 package is looking for funding
  run `npm fund` for details

found 0 vulnerabilities

```


##### 2. package.jsonの依存関係を確認する

```sh:Terminal
$ cat package.json
{
  "name": "node_js_api_sample_1",
  "version": "1.0.0",
  "description": "lighthouse on NodeJS on express by WebAPI",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/webmaster-patche/node_js_api_sample_1.git"
  },
  "keywords": [
    "lighthouse",
    "NodeJS",
    "express",
    "API"
  ],
  "author": "webmaster-patche",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/webmaster-patche/node_js_api_sample_1/issues"
  },
  "homepage": "https://github.com/webmaster-patche/node_js_api_sample_1#readme",
  "dependencies": {
    "express": "^4.17.1",
    "puppeteer": "^2.0.0"
  }
}
```


## lighthouseをインストールする

##### 1. npmでインストールする（package.json追記タイプ）

```sh:Terminal
$ npm install -g lighthouse
/usr/local/bin/lighthouse -> /usr/local/lib/node_modules/lighthouse/lighthouse-cli/index.js
/usr/local/bin/chrome-debug -> /usr/local/lib/node_modules/lighthouse/lighthouse-core/scripts/manual-chrome-launcher.js
+ lighthouse@5.6.0
added 234 packages from 203 contributors in 23.901s
```

##### 後の手順 `http://127.0.0.1:8081/lighthouse/%url%` にアクセスした時に /bin/sh: lighthouse: command not found となる場合

* npm install --save lighthouseではコマンドがインストールされない

* アンインストールする

```sh:Terminal
$ npm uninstall lighthouse
removed 210 packages and audited 176 packages in 2.434s
found 0 vulnerabilities

```

* インストールし直す

```sh:Terminal
$ npm install -g lighthouse
/usr/local/bin/lighthouse -> /usr/local/lib/node_modules/lighthouse/lighthouse-cli/index.js
/usr/local/bin/chrome-debug -> /usr/local/lib/node_modules/lighthouse/lighthouse-core/scripts/manual-chrome-launcher.js
+ lighthouse@5.6.0
added 234 packages from 203 contributors in 23.901s
```


##### 2. package.jsonの依存関係を編集する

```sh:Terminal
$ vi package.json 
{
  "name": "node_js_api_sample_1",
  "version": "1.0.0",
  "description": "lighthouse on NodeJS on express by WebAPI",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/webmaster-patche/node_js_api_sample_1.git"
  },
  "keywords": [
    "lighthouse",
    "NodeJS",
    "express",
    "API"
  ],
  "author": "webmaster-patche",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/webmaster-patche/node_js_api_sample_1/issues"
  },
  "homepage": "https://github.com/webmaster-patche/node_js_api_sample_1#readme",
  "dependencies": {
    "express": "^4.17.1",
    "lighthouse": "^5.6.0",
    "puppeteer": "^2.0.0"
  }
}
```

## index.jsを編集する

##### 1. light_houseを外部ファイルとしてインクルードする

```javascript:index.js
// expressモジュールを読み込む
const express = require('express');

// expressアプリを生成する
const app = express();

// ポート3000でサーバを立てる
var server = app.listen(8081, () => console.log(`Node.js Linsten Port: ${server.address().port}`) );

/* start Including export js */

// include lighthouse.js
var lighthouse = require('./lighthouse');

/*  end Including export js  */

// ルート（http://localhost/）にアクセスしてきたときに「Hello」を返す
app.get('/', (req, res) => res.send('Hello world'));

// light_house_scoreにアクセスしてきたときに、jsonでスコアを返す
app.get('/lighthouse/:url', function(req, res) {
  lighthouse.getLighthouseScore(decodeURI(req.params.url))
    .then(function(result) {
    console.log(`result: ${result}`);
    res.send(result);
  });
});
```

##### 2. lighthouse.jsを編集する

```javascript:lighthouse.js
const execSync = require('child_process').execSync;

exports.getLighthouseScore = (url) => {
  return new Promise((resolve, reject) => {
    try {
      console.log(`light house URL: ${url}`);

      // Lighthouse CLIを実行
      const result = execSync(`lighthouse "${url}" --output json --quiet`, {timeout: 60000}).toString();
      const stats = JSON.parse(result);

      const scoreMap = Object.entries(stats.categories).reduce((acc, [key, val]) => {
        return Object.assign({}, acc, {[val.title]: val.score ? parseInt(val.score * 100) : 0 });
      }, {});

      resolve(scoreMap);
    } catch(e) {
      reject({});
      execSync
    } 
  });
}
```

##### 3. Web-apサーバ起動

```sh:Terminal
$ node index.js
```

* `http://127.0.0.1:8081/lighthouse/https%3A%2F%2Fqiita.com%2F` にアクセスする

![スクリーンショット 2020-01-21 3.20.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179927/3e66dd52-04f6-c56a-047c-6f5ad7cc4829.png)


```text:Response
{"Performance":64,"Accessibility":44,"Best Practices":86,"SEO":90,"Progressive Web App":74}
{"Performance":28,"Accessibility":44,"Best Practices":86,"SEO":90,"Progressive Web App":74}
```

* 停止する場合は `Ctrl + C` でシグナルを送信します

## リクエストパラメータで複数回指定を制御する

##### 1. index.jsを編集する

```javascript:index.js
// expressモジュールを読み込む
const express = require('express');

// expressアプリを生成する
const app = express();

// ポート3000でサーバを立てる
var server = app.listen(8081, () => console.log(`Node.js Linsten Port: ${server.address().port}`) );

/* start Including export js */

// include lighthouse.js

var lighthouse = require('./lighthouse');
const consts = require('./const');

/*  end Including export js  */

// ルート（http://localhost/）にアクセスしてきたときに「Hello」を返す
app.get('/', (req, res) => res.send('Hello world'));

// light_house_scoreにアクセスしてきたときに、jsonでスコアを返す
/* Request Parameter
 *  /lighthouse/%encoded url%?%query string(?param=value[&param=value]...%
 *  encoded url: light houseで計測するurl（Base64 encondeされたURL）
 *  query string: term 回数
 */
app.get('/lighthouse/:url', function(req, res) {

  console.log(`request paraemter: ${req.query.term} / ${req.params.url}`);

  var resultsMap = new Map();
  var limit = req.query.term || 1;

  for(loop = 0; loop < limit; loop++) {
    lighthouse.getLighthouseScore(decodeURI(req.params.url))
      .then(function(result) {
      // console.log(consts.lighthouseScoreFile());
      var resultMap = lighthouse.getLighthouseScoreMap(consts.lighthouseScoreFile());
      // map set
      resultMap.forEach( function(v, k) {
        if (resultsMap.has(k)) {
          var arr = resultMap.get(k);
          arr.push(v);
          resultsMap.set(k, arr);
        } else {
          resultsMap.set(k, [v]);
        }
      });
    });
  }

  // res.send( JSON.stringify( Array.from(resultsMap).reduce( (sum, [v,k]) => (sum[v]=k, sum), {}) ) );
  res.send( JSON.stringify( Array.from(resultsMap).reduce( (sum, [k,v]) => (sum[k]=v, sum), {} ) ) );

});
```

##### 2. lighthouse.js を編集する

```javascript:lighthouse.js
const execSync = require('child_process').execSync;
const fs = require('fs');
const consts = require('./const');

exports.getLighthouseScore = (url) => {
  return new Promise((resolve, reject) => {
    try {
      // console.log(`light house URL: ${url}`);
      console.log(`lighthouse "${url}" --save-assets --output json --output-path ${consts.lighthouseScoreFile()} --quiet`);

      // Lighthouse CLIを実行
      const result = execSync(`lighthouse "${url}" --save-assets --output json --output-path ${consts.lighthouseScoreFile()} --quiet`, {timeout: 60000});
      // const stats = JSON.parse(result);

      // const scoreMap = Object.entries(stats.categories).reduce((acc, [key, val]) => {
      //  return Object.assign({}, acc, {[val.title]: val.score ? parseInt(val.score * 100) : 0 });
      //}, {});

      //resolve(scoreMap);
      resolve();
    } catch(e) {
      reject({});
      //execSync
    }
  });
}
exports.getLighthouseScoreMap = (file) => {
  var json = JSON.parse(fs.readFileSync(file, 'utf8'));

  var importMap = new Map(Object.entries(json));
  // console.log(importMap.get("audits")['first-contentful-paint']["displayValue"]);
  // console.log(importMap.get("audits")['first-meaningful-paint']["displayValue"]);
  // console.log(importMap.get("audits")['speed-index']["displayValue"]);
  // console.log(importMap.get("audits")['first-cpu-idle']["displayValue"]);
  // console.log(importMap.get("audits")['interactive']["displayValue"]);
  // console.log(importMap.get("audits")['max-potential-fid']["displayValue"]);

  return resultMap = new Map([
    ["first-contentful-paint", importMap.get("audits")['first-contentful-paint']["displayValue"]],
    ["first-meaningful-paint", importMap.get("audits")['first-meaningful-paint']["displayValue"]],
    ["speed-index", importMap.get("audits")['speed-index']["displayValue"]],
    ["first-cpu-idle", importMap.get("audits")['first-cpu-idle']["displayValue"]],
    ["interactive", importMap.get("audits")['interactive']["displayValue"]],
    ["max-potential-fid", importMap.get("audits")['max-potential-fid']["displayValue"]]
  ]);
}
```

##### 3. const.js を作成する

```javascript:const.js
exports.lighthouseScoreFile = () => { return "/Users/webmaster-patche/node_js_api_sample_1/result.json" }
```

##### これで動くと思いきや？！

```text:Response
{}
```

##### 5. ログを仕込んでみる

```javascript:index.js
// expressモジュールを読み込む
const express = require('express');

// expressアプリを生成する
const app = express();

// ポート3000でサーバを立てる
var server = app.listen(8081, () => console.log(`Node.js Linsten Port: ${server.address().port}`) );

/* start Including export js */

// include lighthouse.js

var lighthouse = require('./lighthouse');
const consts = require('./const');

/*  end Including export js  */

// ルート（http://localhost/）にアクセスしてきたときに「Hello」を返す
app.get('/', (req, res) => res.send('Hello world'));

// light_house_scoreにアクセスしてきたときに、jsonでスコアを返す
/* Request Parameter
 *  /lighthouse/%encoded url%?%query string(?param=value[&param=value]...%
 *  encoded url: light houseで計測するurl（Base64 encondeされたURL）
 *  query string: term 回数
 */
app.get('/lighthouse/:url', function(req, res) {

  console.log(`request paraemter: ${req.query.term} / ${req.params.url}`);

  var resultsMap = new Map();
  var limit = req.query.term || 1;

  for(loop = 0; loop < limit; loop++) {
    lighthouse.getLighthouseScore(decodeURI(req.params.url))
      .then(function(result) {
      // console.log(consts.lighthouseScoreFile());
      var resultMap = lighthouse.getLighthouseScoreMap(consts.lighthouseScoreFile());
      // map set
      resultMap.forEach( function(v, k) {
        if (resultsMap.has(k)) {
          var arr = resultMap.get(k);
          arr.push(v);
          resultsMap.set(k, arr);
        } else {
          resultsMap.set(k, [v]);
        }
        /* このログ */
        console.log(`${k} > ${v}`);
      });
      /* このログ */
      console.log(resultsMap);
    });
  }

  // res.send( JSON.stringify( Array.from(resultsMap).reduce( (sum, [v,k]) => (sum[v]=k, sum), {}) ) );
  res.send( JSON.stringify( Array.from(resultsMap).reduce( (sum, [k,v]) => (sum[k]=v, sum), {} ) ) );

});
```

```text:デバッグログ
request paraemter: 2 / https://qiita.com/
lighthouse "https://qiita.com/" --save-assets --output json --output-path /Users/webmaster-patche/node_js_api_sample_1/result.json --quiet
Map {}
lighthouse "https://qiita.com/" --save-assets --output json --output-path /Users/webmaster-patche/node_js_api_sample_1/result.json --quiet
Map {}
Map {}
first-contentful-paint > 2.3 s
has: false
first-meaningful-paint > 2.3 s
has: false
speed-index > 3.2 s
has: false
first-cpu-idle > 7.9 s
has: false
interactive > 9.1 s
has: false
max-potential-fid > 200 ms
has: false
first-contentful-paint > 2.3 s
has: true
first-meaningful-paint > 2.3 s
has: true
speed-index > 3.2 s
has: true
first-cpu-idle > 7.9 s
has: true
interactive > 9.1 s
has: true
max-potential-fid > 200 ms
has: true
```

明らかにレポート結果の二重読み込みをした上、Mapに一向に結果が反映されない

### 非同期処理を廃止（Promise）

##### 1. index.js を編集する

```javascript:index.js
// expressモジュールを読み込む
const express = require('express');

// expressアプリを生成する
const app = express();

// ポート3000でサーバを立てる
var server = app.listen(8081, () => console.log(`Node.js Linsten Port: ${server.address().port}`) );

/* start Including export js */

// include lighthouse.js

var lighthouse = require('./lighthouse');
const consts = require('./const');

/*  end Including export js  */

// ルート（http://localhost/）にアクセスしてきたときに「Hello」を返す
app.get('/', (req, res) => res.send('Hello world'));

// light_house_scoreにアクセスしてきたときに、jsonでスコアを返す
/* Request Parameter
 *  /lighthouse/%encoded url%?%query string(?param=value[&param=value]...%
 *  encoded url: light houseで計測するurl（Base64 encondeされたURL）
 *  query string: term 回数
 */
app.get('/lighthouse/:url', function(req, res) {

  console.log(`request paraemter: ${req.query.term} / ${req.params.url}`);

  var resultsMap = new Map();
  var limit = req.query.term || 1;

  for(loop = 0; loop < limit; loop++) {
    lighthouse.getLighthouseScore(decodeURI(req.params.url));
      // console.log(consts.lighthouseScoreFile());
      var resultMap = lighthouse.getLighthouseScoreMap(consts.lighthouseScoreFile());
      // map set
      resultMap.forEach( function(v, k) {
        if (resultsMap.has(k)) {
          var arr = resultsMap.get(k);
          arr.push(v);
          resultsMap.set(k, arr);
        } else {
          resultsMap.set(k, [v]);
        }
      });
  }
  res.send( JSON.stringify( Array.from(resultsMap).reduce( (sum, [k,v]) => (sum[k]=v, sum), {} ) ) );
});
```

##### 2. lighthouse.js を編集する

```javascript:lighthouse.js
const execSync = require('child_process').execSync;
const fs = require('fs');
const consts = require('./const');
 
exports.getLighthouseScore = async (url) => {
    try {
      console.log(`lighthouse "${url}" --save-assets --output json --output-path ${consts.lighthouseScoreFile()} --quiet`);

      // Lighthouse CLIを実行
      const result = execSync(`lighthouse "${url}" --save-assets --output json --output-path ${consts.lighthouseScoreFile()} --quiet`, {timeout: 60000});
    } catch(e) {
    }
}
exports.getLighthouseScoreMap = (file) => {
  var json = JSON.parse(fs.readFileSync(file, 'utf8'));
  var importMap = new Map(Object.entries(json));
  
  var resultMap = new Map([
    ["first-contentful-paint", importMap.get("audits")['first-contentful-paint']["displayValue"]],
    ["first-meaningful-paint", importMap.get("audits")['first-meaningful-paint']["displayValue"]],
    ["speed-index", importMap.get("audits")['speed-index']["displayValue"]],
    ["first-cpu-idle", importMap.get("audits")['first-cpu-idle']["displayValue"]],
    ["interactive", importMap.get("audits")['interactive']["displayValue"]],
    ["max-potential-fid", importMap.get("audits")['max-potential-fid']["displayValue"]]
  ]);
  return resultMap;
}
```

##### 4. 起動する

```sh:Terminal
$ node index.js
```

* `http://127.0.0.1:8081/lighthouse/https%3A%2F%2Fqiita.com%2F?term=15` にアクセスする

![スクリーンショット 2020-01-21 3.20.09.png]()


```json:Response
{"first-contentful-paint":["2.4 s","2.0 s","2.1 s","2.1 s","1.8 s","2.1 s","2.1 s","1.9 s","2.1 s","1.9 s","2.3 s","2.7 s","1.9 s","2.1 s","1.9 s"],"first-meaningful-paint":["2.4 s","2.0 s","2.1 s","2.5 s","2.3 s","2.1 s","2.6 s","1.9 s","3.1 s","2.3 s","2.3 s","2.9 s","1.9 s","2.6 s","1.9 s"],"speed-index":["3.9 s","4.3 s","5.3 s","4.5 s","4.7 s","3.8 s","5.6 s","4.7 s","5.1 s","4.2 s","5.1 s","6.0 s","3.7 s","5.4 s","4.6 s"],"first-cpu-idle":["9.9 s","9.6 s","9.1 s","9.6 s","9.5 s","8.2 s","7.7 s","9.2 s","9.2 s","9.4 s","10.1 s","10.2 s","8.5 s","7.8 s","9.5 s"],"interactive":["11.2 s","10.8 s","10.0 s","10.8 s","10.6 s","12.2 s","10.4 s","10.1 s","10.5 s","10.6 s","11.3 s","11.5 s","9.7 s","9.9 s","10.6 s"],"max-potential-fid":["1,500 ms","480 ms","180 ms","510 ms","240 ms","460 ms","420 ms","430 ms","440 ms","630 ms","430 ms","1,200 ms","440 ms","480 ms","500 ms"]}
```

```json:Beautify
{
  "first-contentful-paint": [
    "2.4 s",
    "2.0 s",
    "2.1 s",
    "2.1 s",
    "1.8 s",
    "2.1 s",
    "2.1 s",
    "1.9 s",
    "2.1 s",
    "1.9 s",
    "2.3 s",
    "2.7 s",
    "1.9 s",
    "2.1 s",
    "1.9 s"
  ],
  "first-meaningful-paint": [
    "2.4 s",
    "2.0 s",
    "2.1 s",
    "2.5 s",
    "2.3 s",
    "2.1 s",
    "2.6 s",
    "1.9 s",
    "3.1 s",
    "2.3 s",
    "2.3 s",
    "2.9 s",
    "1.9 s",
    "2.6 s",
    "1.9 s"
  ],
  "speed-index": [
    "3.9 s",
    "4.3 s",
    "5.3 s",
    "4.5 s",
    "4.7 s",
    "3.8 s",
    "5.6 s",
    "4.7 s",
    "5.1 s",
    "4.2 s",
    "5.1 s",
    "6.0 s",
    "3.7 s",
    "5.4 s",
    "4.6 s"
  ],
  "first-cpu-idle": [
    "9.9 s",
    "9.6 s",
    "9.1 s",
    "9.6 s",
    "9.5 s",
    "8.2 s",
    "7.7 s",
    "9.2 s",
    "9.2 s",
    "9.4 s",
    "10.1 s",
    "10.2 s",
    "8.5 s",
    "7.8 s",
    "9.5 s"
  ],
  "interactive": [
    "11.2 s",
    "10.8 s",
    "10.0 s",
    "10.8 s",
    "10.6 s",
    "12.2 s",
    "10.4 s",
    "10.1 s",
    "10.5 s",
    "10.6 s",
    "11.3 s",
    "11.5 s",
    "9.7 s",
    "9.9 s",
    "10.6 s"
  ],
  "max-potential-fid": [
    "1,500 ms",
    "480 ms",
    "180 ms",
    "510 ms",
    "240 ms",
    "460 ms",
    "420 ms",
    "430 ms",
    "440 ms",
    "630 ms",
    "430 ms",
    "1,200 ms",
    "440 ms",
    "480 ms",
    "500 ms"
  ]
}
```

* 停止する場合は `Ctrl + C` でシグナルを送信します