国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

目次
Google Lighthouseとは何ですか?
設(shè)定
node.jsでクロムを開く
プログラムで燈臺を?qū)g行します
Lighthouseのレポートを節(jié)約します
ディレクトリの作成
レポートを保存します
Lighthouseレポートの比較
前のレポートに対して新しいレポートを比較してください
2つのレポートを比較します
比較ロジック
Complete source code
Next steps
ホームページ ウェブフロントエンド CSSチュートリアル node.jsツールを作成して、Google Lighthouseレポートを記録および比較する

node.jsツールを作成して、Google Lighthouseレポートを記録および比較する

Apr 09, 2025 am 09:18 AM

node.jsツールを作成して、Google Lighthouseレポートを記録および比較する

このチュートリアルでは、node.jsにシンプルなツールを作成してコマンドラインを介してGoogle燈臺監(jiān)査を?qū)g行し、JSON形式で生成するレポートを保存して、Webサイトを成長および開発するにつれてWebパフォーマンスを監(jiān)視できるようにして、それらを比較する方法を段階的に紹介します。

これがプログラムでGoogle Lighthouseで働く方法について學(xué)ぶことに関心のある開発者にとって、良い紹介として役立つことを願っています。

しかし、最初に、初心者のために…

Google Lighthouseとは何ですか?

Google Lighthouseは、Web開発者のユーティリティベルトで利用できる最も自動化されたツールの1つです。これにより、全體的な品質(zhì)の尺度を形成できる多くの重要な領(lǐng)域でWebサイトをすばやく監(jiān)査することができます。これらは:

  • パフォーマンス
  • アクセシビリティ
  • ベストプラクティス
  • SEO
  • プログレッシブWebアプリ

監(jiān)査が完了すると、ウェブサイトがうまく機(jī)能することについてレポートが生成されます。後者は、ページを改善するための次のステップの指標(biāo)として機(jī)能することを意図しています。

これが完全なレポートの外観です。

他の一般的な診斷およびWebパフォーマンスメトリックに加えて、レポートの非常に便利な機(jī)能は、各重要な領(lǐng)域が0?100の間のカラーコーディングスコアに集約されていることです。

これにより、開発者はさらなる分析なしでWebサイトの品質(zhì)を迅速に評価できるだけでなく、利害関係者やクライアントなどの技術(shù)者以外の人々も理解することができます。

たとえば、これは、燈臺のアクセシビリティスコアが50ポイント上昇してグリーンに上昇した後、ウェブサイトのアクセシビリティを改善するために時間を費(fèi)やした後、マーケティングのヘザーとの勝利を共有する方がはるかに簡単です。

しかし、同様に、プロジェクトマネージャーのサイモンは、スピードインデックスまたは最初のコンテンツペイントの意味を理解していないかもしれませんが、燈臺レポートが赤の深い膝を示す燈臺レポートを見たとき、彼はあなたがまだやるべきことを知っています。

ChromeまたはEdgeの最新バージョンにいる場合は、DevToolsを使用して現(xiàn)在自分で燈臺監(jiān)査を?qū)g行できます。方法は次のとおりです。

また、PageSpeed InsightsまたはWebPagetestなどの人気のあるパフォーマンスツールを介して、オンラインで燈臺監(jiān)査を?qū)g行することもできます。

ただし、今日では、ノードモジュールとしての燈臺のみに関心があります。これにより、プログラムでツールを使用してWebパフォーマンスメトリックを監(jiān)査、記録、比較することができます。

その方法を見つけましょう。

設(shè)定

まず、まだ持っていない場合は、node.jsが必要になります。それをインストールするには、數(shù)百萬の異なる方法があります。 HomeBrewパッケージマネージャーを使用しますが、必要に応じてnode.js Webサイトからインストーラーを直接ダウンロードすることもできます。このチュートリアルはnode.js v10.17.0を念頭に置いて書かれていますが、過去數(shù)年間にリリースされたほとんどのバージョンではうまく機(jī)能する可能性が非常に高いです。

また、燈臺監(jiān)査を?qū)g行する方法であるため、Chromeがインストールされる必要があります。

次に、プロジェクトの新しいディレクトリを作成し、コンソールでCDにCDに作成します。次に、NPM initを?qū)g行して、package.jsonファイルの作成を開始します。この時點で、ファイルが作成されるまで、できるだけ多くのこのスキップをスキップするために、Enterキーを何度もバッシングすることをお勧めします。

次に、プロジェクトディレクトリに新しいファイルを作成しましょう。私は私のlh.jsに電話しましたが、あなたが望むものは何でも自由に電話してください。これには、ツールのすべてのJavaScriptが含まれます。選択したテキストエディターでそれを開き、今のところ、Console.logステートメントを書きます。

 console.log( 'hello world');

次に、コンソールで、CWD(現(xiàn)在のワーキングディレクトリ)がプロジェクトディレクトリとノードLH.JSを?qū)g行し、使用したものを何でも置き換えます。

あなたは見るべきです:

 $ node lh.js
こんにちは世界

そうでない場合は、ノードのインストールが機(jī)能していることを確認(rèn)すると、間違いなく正しいプロジェクトディレクトリにいます。

これが邪魔にならないように、私たちはツール自體の開発に進(jìn)むことができます。

node.jsでクロムを開く

プロジェクトの最初の依存関係である燈臺自體をインストールしましょう。

 npmインストール燈臺 -  save-dev

これにより、すべてのパッケージのファイルを含むnode_modulesディレクトリが作成されます。 GITを使用している場合、これでやりたいことは、.gitignoreファイルに追加することだけです。

LH.JSでは、次にTest Console.log()を削除し、燈臺モジュールをインポートして、コードで使用できるようにする必要があります。そうするように:

 const lighthouse = require( 'lighthouse');

その下では、燈臺の依存関係の1つであるChrome-Launcherというモジュールをインポートする必要があり、監(jiān)査を?qū)g行できるようにノードを単獨でChromeを起動できるようにします。

 const lighthouse = require( 'lighthouse');
const chromelauncher = require( 'chrome-launcher');

これらの2つのモジュールにアクセスできるようになったので、Chromeを開き、Lighthouse監(jiān)査を?qū)g行し、レポートをコンソールに印刷する?yún)g純なスクリプトを作成しましょう。

URLをパラメーターとして受け入れる新しい関數(shù)を作成します。 node.jsを使用してこれを?qū)g行するため、厄介なインターネットエクスプローラーユーザーを心配する必要がないため、ES6構(gòu)文を安全に使用できます。

 const launchchrome =(url)=> {

}

関數(shù)內(nèi)で、最初に行う必要があるのは、インポートしたChrome-Launcherモジュールを使用してChromeを開くことで、URLパラメーターを介して渡される引數(shù)に送信します。

launch()メソッドとstartingurlオプションを使用してこれを行うことができます。

 const launchchrome = url => {
  chromeLauncher.launch({
    startingurl:url
  });
};

以下の関數(shù)を呼び出し、選択したURLを渡すと、ノードスクリプトが実行されると、URLでChromeが開かれます。

 LaunchChrome( 'https://www.lukeharrison.dev');

起動関數(shù)は実際に約束を返します。これにより、いくつかの便利な方法とプロパティを含むオブジェクトにアクセスできます。

たとえば、以下のコードを使用して、Chromeを開き、オブジェクトをコンソールに印刷し、3秒後にKill()メソッドを使用してChromeを閉じることができます。

 const launchchrome = url => {
  ChromeLauncher
    。打ち上げ({
      startingurl:url
    })
    .then(chrome => {
      console.log(chrome);
      setimeout(()=> chrome.kill()、3000);
    });
};

LaunchChrome( "https://www.lukeharrison.dev");

Chromeが把握したので、Lighthouseに移りましょう。

プログラムで燈臺を?qū)g行します

まず、LaunchChrome()関數(shù)を最終的な機(jī)能をより反映したものに変更してみましょう。邪魔にならないように、チュートリアルで前半でインポートした燈臺モジュールを使用できるようになりました。

Chrome LauncherのThen機(jī)能では、ブラウザが開いてからのみ実行される場合にのみ、燈臺のURL引數(shù)を渡し、このWebサイトの監(jiān)査をトリガーします。

 const launchchromeandrunlighthouse = url => {
  ChromeLauncher
    。打ち上げ({
      startingurl:url
    })
    .then(chrome => {
      const opts = {
        ポート:Chrome.port
      };
      Lighthouse(url、opts);
    });
};

LaunchChromeandrunlighthouse( "https://www.lukeharrison.dev");

LighthouseインスタンスをChromeブラウザウィンドウにリンクするには、URLとともにポートを通過する必要があります。

このスクリプトを今すぐ実行する場合、コンソールでエラーが発生します。

 (ノード:47714)unhandledpromiserejectionwarning:エラー:おそらく、同じオリジンに複數(shù)のタブが開いているでしょう。

これを修正するには、Chrome Launcherからstartingurlオプションを削除し、LighthouseをここからURLナビゲーションを処理させるだけです。

 const launchchromeandrunlighthouse = url => {
  chromeLauncher.launch()。then(chrome => {
    const opts = {
      ポート:Chrome.port
    };
    Lighthouse(url、opts);
  });
};

このコードを?qū)g行する場合、何かが間違いなく起こっているように見えることに気付くでしょう。燈臺の監(jiān)査が間違いなく実行されていることを確認(rèn)するために、コンソールでフィードバックを受け取っていないだけでなく、以前のようにChromeインスタンス自體も閉鎖されていません。

ありがたいことに、Lighthouse()Functionは、監(jiān)査結(jié)果にアクセスできる約束を返します。

Chromeを殺してから、結(jié)果オブジェクトのレポートプロパティを介してJSON形式の端末にそれらの結(jié)果を印刷しましょう。

 const launchchromeandrunlighthouse = url => {
  chromeLauncher.launch()。then(chrome => {
    const opts = {
      ポート:Chrome.port
    };
    lighthouse(url、opts).then(result => {
      Chrome.kill();
      console.log(results.report);
    });
  });
};

コンソールはこれらの結(jié)果を表示する最良の方法ではありませんが、クリップボードにコピーして燈臺レポートビューアーにアクセスする場合、ここに貼り付けると、その栄光のすべてのレポートが表示されます。

この時點で、laintChromeandrunlighthouse()機(jī)能を?qū)g行して、実行が終了したらレポートを返すために、コードを少し整理することが重要です。これにより、JavaScriptの亂雑なピラミッドをもたらすことなく、後でレポートを処理できます。

 const lighthouse = require( "lighthouse");
const chromelauncher = require( "Chrome-Launcher");

const launchchromeandrunlighthouse = url => {
  return chromelauncher.launch()。then(chrome => {{
    const opts = {
      ポート:Chrome.port
    };
    lighthouse(url、opts)を返します。
      chrome.kill()。then(()=> results.report);
    });
  });
};

LaunchChromeanDrunlighthouse( "https://www.lukeharrison.dev").then(result => {{
  console.log(results);
});

気づいたかもしれないことの1つは、私たちのツールが現(xiàn)時點で1つのウェブサイトのみを監(jiān)査できることです。これを変更して、コマンドラインを介してURLを引數(shù)として渡すことができます。

コマンドラインの引數(shù)を扱うことで痛みを取り除くために、Yargsというパッケージでそれらを処理します。

 npmインストール -  save-dev yargs

次に、ChromeランチャーとLighthouseとともにスクリプトの上部にインポートします。ここではそのargv関數(shù)のみが必要です。

 const lighthouse = require( 'lighthouse');
const chromelauncher = require( 'chrome-launcher');
const argv = require( 'yargs')。argv;

これは、そうするような端末でコマンドライン引數(shù)を渡す場合を意味します。

 node lh.js -url https://www.google.co.uk

…次のように、スクリプトの引數(shù)にアクセスできます。

 const url = argv.url // https://www.google.co.uk

スクリプトを編集して、コマンドラインURL引數(shù)を関數(shù)のURLパラメーターに渡しましょう。引數(shù)が渡されなかった場合に備えて、IFステートメントとエラーメッセージを介して少しセーフティネットを追加することが重要です。

 if(argv.url){
  LaunchChromeanDrunlighthouse(argv.url).then(result => {{
    console.log(results);
  });
} それ以外 {
  「あなたは燈臺にURLを渡していない」を投げます。
}

田田! Chromeを起動し、JSON形式のターミナルにレポートを印刷する前に、プログラムで燈臺監(jiān)査を?qū)g行するツールがあります。

Lighthouseのレポートを節(jié)約します

レポートをコンソールに印刷することは、その內(nèi)容を簡単に読み取ることができず、將來の使用のために保存されないため、あまり役に立ちません。チュートリアルのこのセクションでは、この動作を変更して、各レポートが獨自のJSONファイルに保存されます。

さまざまなWebサイトからのレポートを停止するために、そのように整理します。

  • lukeharrison.dev
    • 2020-01-31T18:18:12.648Z.JSON
    • 2020-01-31T19:10:24.110Z.JSON
  • CNN.com
    • 2020-01-14T22:15:10.396z.json
  • LH.JS

レポートには、レポートがいつ生成されたかを示すタイムスタンプでレポートに名前を付けます。これは、2つのレポートファイル名が同じではないことを意味し、レポートを簡単に區(qū)別するのに役立ちます。

私たちの注意を必要とするWindowsには1つの問題があります。コロン(:)はファイル名の違法な性格です。この問題を軽減するために、任意のコロンをアンダースコア(_)に置き換えるため、典型的なレポートファイル名は次のようになります。

  • 2020-01-31T18_18_12.648Z.JSON

ディレクトリの作成

まず、コマンドラインURL引數(shù)を操作して、ディレクトリ名に使用できるようにする必要があります。

これには、wwwを削除するだけではありません。これは、www(例:www.foo.com/bar)に座っていないWebページで実行される監(jiān)査を説明する必要があるためです。

これらのURLについては、無効な文字を再度アンダースコアに置き換えます。そうすれば、https://www.foo.com/barで監(jiān)査を?qū)g行した場合、レポートを含む結(jié)果のディレクトリ名はfoo.com_barになります。

URLの処理を容易にするために、URLと呼ばれるネイティブNode.jsモジュールを使用します。これは、他のパッケージと同様にインポートでき、package.jsonに追加してnpm経由でプルすることはできません。

 const lighthouse = require( 'lighthouse');
const chromelauncher = require( 'chrome-launcher');
const argv = require( 'yargs')。argv;
const url = require( 'url');

次に、新しいURLオブジェクトをインスタンス化するために使用しましょう。

 if(argv.url){
  const urlobj = new url(argv.url);

  LaunchChromeanDrunlighthouse(argv.url).then(result => {{
    console.log(results);
  });
}

urlobjをコンソールに印刷する場合、使用できる有用なURLデータがたくさん表示されます。

 $ node lh.js -url https://www.foo.com/bar
url {
  href: 'https://www.foo.com/bar'、
  起源: 'https://www.foo.com'、
  プロトコル: 'https:'、
  ユーザー名: ''、
  パスワード: ''、
  ホスト: 'www.foo.com'、
  ホスト名: 'www.foo.com'、
  ポート: ''、
  パス名: '/bar'、
  検索: ''、
  SearchParams:urlsearchparams {}、
  ハッシュ: ''
}

dirNameという新しい変數(shù)を作成し、HTTPSプロトコルに加えてWWWを削除するために、URLのホストプロパティで文字列置換()メソッドを使用します。

 const urlobj = new url(argv.url);
let dirname = urlobj.host.replace( 'www。'、 '');

ここでletを使用しました。これは、constを再割り當(dāng)てすることができます。これは、URLにパス名がある場合はリファレンスを更新する必要があるため、スラッシュをアンダースコアに置き換える必要があります。これは正規(guī)表現(xiàn)パターンで実行でき、次のようになります。

 const urlobj = new url(argv.url);
let dirname = urlobj.host.replace( "www。"、 "");
if(urlobj.pathname!== "/"){
  dirname = dirname urlobj.pathname.replace(/\ // g、 "_");
}

これで、ディレクトリ自體を作成できます。これは、FS(「ファイルシステム」の略)と呼ばれる別のネイティブnode.jsモジュールを使用することで実行できます。

 const lighthouse = require( 'lighthouse');
const chromelauncher = require( 'chrome-launcher');
const argv = require( 'yargs')。argv;
const url = require( 'url');
const fs = require( 'fs');

mkdir()メソッドを使用してディレクトリを作成できますが、最初にexistssync()メソッドを使用して、node.jsがエラーをスローするため、ディレクトリが既に存在するかどうかを確認(rèn)する必要があります。

 const urlobj = new url(argv.url);
let dirname = urlobj.host.replace( "www。"、 "");
if(urlobj.pathname!== "/"){
  dirname = dirname urlobj.pathname.replace(/\ // g、 "_");
}
if(!fs.existsync(dirname)){
  fs.mkdirsync(dirname);
}

ポイントでスクリプトをテストすると、新しいディレクトリが作成されます。 https://www.bbc.co.uk/newsをURL引數(shù)として渡すと、bbc.co.uk_newsという名前のディレクトリが得られます。

レポートを保存します

LaunchChromeanDrunlighthouse()のその後の関數(shù)では、既存のConsole.logをロジックに置き換えて、レポートをディスクに書き込みます。これは、FSモジュールのWriteFile()メソッドを使用して実行できます。

 LaunchChromeanDrunlighthouse(argv.url).then(result => {{
  fs.WriteFile( "Report.json"、result、err => {
    (err)スローERR;
  });
});

最初のパラメーターはファイル名を表し、2番目はファイルのコンテンツ、3番目は書き込みプロセス中に何か問題が発生した場合にエラーオブジェクトを含むコールバックです。これにより、Report.jsonと呼ばれる新しいファイルが作成されます。

ファイル名としてタイムスタンプを使用して、正しいディレクトリに送信する必要があります。前者は簡単です。

 LaunchChromeanDrunlighthouse(argv.url).then(result => {{
  fs.writefile( `$ {dirname}/report.json`、result、err => {
    (err)スローERR;
  });
});

ただし、後者は、レポートが生成されたときのタイムスタンプを何らかの形で取得する必要があります。ありがたいことに、レポート自體はこれをデータポイントとしてキャプチャし、Fetchtimeプロパティとして保存されます。

Windowsファイルシステムでうまく機(jī)能するように、アンダースコア(_)のコロン(:)を交換することを忘れないでください。

 LaunchChromeanDrunlighthouse(argv.url).then(result => {{
  fs.writefile(
    `$ {dirname}/$ {results [" fetchtime "]。置き換え(/:/g、" _ ")}。json`、
    結(jié)果、
    err => {
      (err)スローERR;
    }
  );
});

Timestamed.jsonのファイル名ではなく、これを今すぐ実行する場合、代わりに次のようなエラーが表示される可能性があります。

 unhandledpromiserejectionwarning:typeRror:未定義のプロパテ?!钢盲瓝Qえ」を読み取ることができません

これは、LighthouseがJavaScriptが消費(fèi)できるオブジェクトではなく、JSON形式でレポートを返しているためです。

ありがたいことに、JSONを自分で解析する代わりに、燈臺に代わりに通常のJavaScriptオブジェクトとしてレポートを返すように頼むことができます。

これには、以下の行を編集する必要があります。

 chrome.kill()。then(()=> results.report);

…に:

 return chrome.kill()。then(()=> results.lhr);

これで、スクリプトを再実行すると、ファイルは正しく命名されます。ただし、開いた場合、殘念ながらコンテンツだけが…

 [オブジェクトオブジェクト]

これは、以前と同じように反対の問題があるからです。最初にJSONオブジェクトに接続することなく、JavaScriptオブジェクトをレンダリングしようとしています。

ソリューションは簡単です。この巨大なオブジェクトの解析や弦楽器にリソースを無駄にしないようにするために、燈臺から両方のタイプを返すことができます。

 lighthouse(url、opts)を返します。
  return chrome.kill()。then(()=> {
    戻る {
      JS:results.lhr、
      JSON:results.report
    };
  });
});

次に、WriteFileインスタンスをこれに変更できます。

 fs.writefile(
  `$ {dirname}/$ {results.js [" fetchtime "]。置換(/:/g、" _ ")}。
  results.json、
  err => {
    (err)スローERR;
  }
);

ソート! Lighthouse監(jiān)査が完了すると、當(dāng)社のツールは、WebサイトURLにちなんで名付けられたディレクトリに、一意のタイムスタンプ付きファイル名を含むファイルにレポートを保存する必要があります。

これは、レポートがより効率的に整理されていることを意味し、レポートがどれだけ保存されても、お互いを無効にしません。

Lighthouseレポートの比較

日常開発中、パフォーマンスの向上に焦點を當(dāng)てたとき、コンソール內(nèi)のレポートを非常に迅速に比較し、正しい方向に向かっているかどうかを確認(rèn)する能力が非常に有用である可能性があります。これを念頭に置いて、この比較機(jī)能の要件は次のはずです。

  1. 燈臺監(jiān)査が完了したときに同じWebサイトに以前のレポートが既に存在する場合、それに対して自動的に比較を?qū)g行し、主要なパフォーマンスメトリックの変更を示します。
  2. また、必要ないかもしれない新しい燈臺レポートを生成することなく、2つのWebサイトからの2つのレポートの主要なパフォーマンスメトリックを比較できるはずです。

レポートのどの部分を比較する必要がありますか?これらは、燈臺レポートの一部として収集された數(shù)値キーパフォーマンスメトリックです。彼らは、ウェブサイトの目的と知覚されたパフォーマンスに関する洞察を提供します。

さらに、Lighthouseは、レポートのこの部分にリストされていないが、比較に含まれる適切な形式である他のメトリックも収集しています。これらは:

  • 最初のバイトまでの時間 -最初のバイトまでの時間は、サーバーが応答を送信する時間を識別します。
  • 総ブロッキング時間 -タスクの長さが50msを超えてミリ秒で表された場合、FCPからインタラクティブまでのすべての期間の合計。
  • 推定入力レイテンシ -推定入力レイテンシは、ページロードの最も忙しい5Sウィンドウ中に、ミリ秒?yún)g位でユーザー入力に応答するためにアプリがどれだけ時間がかかるかの推定値です。レイテンシが50ミリ秒を超える場合、ユーザーはアプリを遅れていると認(rèn)識する場合があります。

メトリック比較はコンソールにどのように出力する必要がありますか?古いメトリックと新しいメトリックを使用して、レポートからレポートにどのように変更されたかを確認(rèn)する?yún)g純なパーセンテージベースの比較を作成します。

迅速なスキャンを可能にするために、個々のメトリックがより速く、遅く、または変化していないかに応じて、個々のメトリックをカラーコードします。

この出力を目指してください。

前のレポートに対して新しいレポートを比較してください

LaunchChromeanDrunlighthouse()関數(shù)のすぐ下にComparePorts()という新しい関數(shù)を作成することから始めましょう。これには、すべての比較ロジックが含まれます。比較に使用される2つのレポートを受け入れるために、2つのパラメーターを提供します。

今のところ、プレースホルダーとして、各レポートのデータをコンソールに印刷するだけで、正しく受信していることを検証します。

 const compareports =(from、to)=> {
  console.log(from ["finalurl"] "" from ["fetchtime"]);
  console.log(to ["finalurl"] "" to ["fetchtime"]);
};

この比較は、新しいレポートの作成後に開始されるため、この関數(shù)を?qū)g行するロジックは、LaunchChromeanDrunlighthouseのThen関數(shù)に配置する必要があります。

たとえば、30のレポートがディレクトリにある場合、どのレポートが最新かを決定し、新しいレポートが比較される前のレポートとして設(shè)定する必要があります。ありがたいことに、私たちはすでにレポートのファイル名としてタイムスタンプを使用することにしたので、これは私たちに仕事をするものを與えてくれます。

まず、既存のレポートを収集する必要があります。このプロセスを簡単にするために、ファイルを検索するときにパターンマッチングが可能になるGLOWと呼ばれる新しい依存関係をインストールします。これは、存在するレポートの數(shù)またはそれらが何と呼ばれるかを予測できないため、これは重要です。

他の依存関係と同じようにインストールします:

 npmインストールグローブ -  save-dev

次に、通常と同じようにファイルの上部にインポートします。

 const lighthouse = require( 'lighthouse');
const chromelauncher = require( 'chrome-launcher');
const argv = require( 'yargs')。argv;
const url = require( 'url');
const fs = require( 'fs');
const glob = require( 'glob');

GLOWを使用して、ディレクトリ內(nèi)のすべてのレポートを収集します。これは、DirName変數(shù)を介して既に知られています。 JavaScriptの実行を継続したくないため、同期オプションをTrueに設(shè)定することが重要です。

 LaunchChromeanDrunlighthouse(argv.url).then(result => {{
  const prevreports = glob( `$ {dirname}/*。json`、{
    同期:true
  });

  // et al

});

このプロセスは、パスの配列を返します。したがって、レポートディレクトリが次のようになった場合:

  • lukeharrison.dev
    • 2020-01-31T10_18_12.648Z.JSON
    • 2020-01-31T10_18_24.110Z.JSON

…その後、結(jié)果の配列は次のようになります。

 [
 'lukeharrison.dev/2020-01-31t10_18_12.648z.json'、
 'lukeharrison.dev/2020-01-31t10_18_24.110z.json'
]

以前のレポートが存在する場合にのみ比較を?qū)g行できるため、この配列を比較ロジックの條件として使用しましょう。

 const prevreports = glob( `$ {dirname}/*。json`、{
  同期:true
});

if(prevreports.length){
}

レポートファイルパスのリストがあり、それらのタイムスタンプ付きファイル名を比較して、最新のファイル名を決定する必要があります。

これは、最初にすべてのファイル名のリストを収集し、ディレクトリ名などの無関係なデータをトリミングし、アンダースコア(_)をコロン(:)を再び有効な日付に戻すように注意する必要があることを意味します。これを行う最も簡単な方法は、別のnode.jsネイティブモジュールを使用することです。

 const path = require( 'path');

そのように、そのように、その解析方法への引數(shù)としてのパスを渡す

Path.Parse( 'lukeharrison.dev/2020-01-31t10_18_24.110Z.json');

この便利なオブジェクトを返します:

 {
  根: ''、
  dir: 'lukeharrison.dev'、
  ベース: '2020-01-31T10_18_24.110Z.JSON'、
  ext: '.json'、
  名前: '2020-01-31T10_18_24.110Z'
}

したがって、すべてのタイムスタンプファイル名のリストを取得するには、これを行うことができます。

 if(prevreports.length){
  日付= [];
  for(prevreportsのレポート){
    dates.push(
      新しい日付(path.parse(prevreports [Report])。name.replace(/_/g、 ":"))
    );
  }
}

私たちのディレクトリが次のように見えた場合、これもまた次のように見えます

  • lukeharrison.dev
    • 2020-01-31T10_18_12.648Z.JSON
    • 2020-01-31T10_18_24.110Z.JSON

結(jié)果:

 [
 '2020-01-31T10:18:12.648Z'、
 '2020-01-31T10:18:24.110Z'
]

日付の便利なことは、デフォルトで本質(zhì)的に匹敵することです。

 const alpha = new Date( '2020-01-31');
const bravo = new Date( '2020-02-15');

console.log(alpha> bravo); // 間違い
console.log(bravo> alpha); // 真実

したがって、還元関數(shù)を使用することにより、最新のものだけが殘るまで日付の配列を減らすことができます。

日付= [];
for(prevreportsのレポート){
  dates.push(new date(path.parse(pretreports [Report])。name.replace(/_/g、 ":")));
}
const max = dates.reduce(function(a、b){
  return math.max(a、b);
});

マックスの內(nèi)容をコンソールに印刷する場合、UNIXタイムスタンプを投げるので、最新の日付を正しいISO形式に戻すために別のラインを追加する必要があります。

 const max = dates.reduce(function(a、b){
 return math.max(a、b);
});
const retryReport = new Date(max).toIsString();

これらがレポートのリストであると仮定します。

  • 2020-01-31T23_24_41.786Z.JSON
  • 2020-01-31T23_25_36.827Z.JSON
  • 2020-01-31T23_37_56.856Z.JSON
  • 2020-01-31T23_39_20.459Z.JSON
  • 2020-01-31T23_56_50.959Z.JSON

最近のレポートの値は、2020-01-31T23:56:50.959zです。

最新のレポートがわかったので、次にその內(nèi)容を抽出する必要があります。最近のレポート変數(shù)の下に最近のReportContentsと呼ばれる新しい変數(shù)を作成し、空の関數(shù)を割り當(dāng)てます。

この関數(shù)は、手動で呼び出すのではなく、常に実行する必要があることがわかっているため、JavaScriptパーサーが到達(dá)したときにそれ自體で実行されるIFFE(すぐに呼び出された関數(shù)式)に変えることは理にかなっています。これは、余分な括弧によって表されます。

 const restryReportContents =(()=> {

})();

この関數(shù)では、ネイティブFSモジュールのreadfilesync()メソッドを使用して、最新のレポートの內(nèi)容を返すことができます。これはJSON形式であるため、通常のJavaScriptオブジェクトに解析することが重要です。

 const restryReportContents =(()=> {
  const output = fs.readfilesync(
    dirname "/" starterreport.replace(/:/g、 "_") ".json"、
    「UTF8」、
    (err、results)=> {
      結(jié)果を返します。
    }
  );
  return json.parse(output);
})();

そして、それはComparePorts()関數(shù)を呼び出し、現(xiàn)在のレポートと最新のレポートの両方を引數(shù)として渡す問題です。

 ComparePorts(最近のReportContents、results.js);

現(xiàn)時點では、これはコンソールにいくつかの詳細(xì)を印刷するだけで、レポートデータをテストできるようになります。

 https://www.lukeharrison.dev/ 2020-02-01T00:25:06.918Z
https://www.lukeharrison.dev/ 2020-02-01T00:25:42.169z

この時點でエラーが発生した場合は、チュートリアルの前半から有効なコンテンツなしでレポートを削除してください。JSONファイルまたはレポートを試してください。

2つのレポートを比較します

殘りの重要な要件は、2つのWebサイトからの任意の2つのレポートを比較する機(jī)能でした。これを?qū)g裝する最も簡単な方法は、ユーザーがコマンドライン引數(shù)として完全なレポートファイルパスを渡すことができることです。

コマンドラインでは、これは次のようになります。

 Node LH.JS  -  From LukeHarrison.dev/2020-02-01t00:25:06.918z-to-to CNN.com/2019-12-16T15:12:07.169z

これを達(dá)成するには、URLコマンドライン引數(shù)の存在をチェックする條件付きIFステートメントを編集する必要があります。追加のチェックを追加して、ユーザーがF(xiàn)romとPathに渡されたばかりであるかどうかを確認(rèn)します。それ以外の場合は、以前のようにURLをチェックします。これにより、新しい燈臺監(jiān)査を防ぎます。

 if(argv.from && argv.to){

} else if(argv.url){
 // et al
}

これらのJSONファイルの內(nèi)容を抽出し、それらをJavaScriptオブジェクトに解析してから、それらをComparePorts()関數(shù)に渡しましょう。

最新のレポートを取得する前に、すでにJSONを解析しました。この機(jī)能を獨自のヘルパー関數(shù)に外挿して、両方の場所で使用できます。

最近のReportContents()関數(shù)をベースとして使用して、引數(shù)としてファイルパスを受け入れるgetContents()と呼ばれる新しい関數(shù)を作成します。 JavaScriptパーサーが見つけたらすぐに実行したくないので、これはIFFEではなく通常の機(jī)能であることを確認(rèn)してください。

 const getContents = pathstr => {
  const output = fs.readfilesync(pathstr、 "utf8"、(err、results)=> {
    結(jié)果を返します。
  });
  return json.parse(output);
};

const compareports =(from、to)=> {
  console.log(from ["finalurl"] "" from ["fetchtime"]);
  console.log(to ["finalurl"] "" to ["fetchtime"]);
};

次に、最近のReportContents()関數(shù)を更新して、代わりにこの外挿されたヘルパー関數(shù)を使用します。

 const restryReportContents = getContents(dirname '/' stromageReport.Replace(/:/g、 '_') '.json');

新しい條件に戻って、比較レポートの內(nèi)容をComparePorts()関數(shù)に渡す必要があります。

 if(argv.from && argv.to){
  ComparEReports(
    getContents(argv.from ".json")、
    getContents(argv.to ".json")
  );
}

以前のように、これはコンソールのレポートに関する基本的な情報を印刷して、すべて正常に機(jī)能していることを知らせる必要があります。

 node lh.js  -  from lukeharrison.dev/2020-01-31t23_24_41.786z-to to lukeharrison.dev/2020-02-01t11_16_25.25.221z

につながる:

 https://www.lukeharrison.dev/ 2020-01-31t23_24_41.786z
https://www.lukeharrison.dev/ 2020-02-01t11_16_25.221z

比較ロジック

開発のこの部分では、比較ロジックを構(gòu)築して、ComparePorts()関數(shù)によって受信された2つのレポートを比較します。

燈臺が返されるオブジェクト內(nèi)には、パフォーマンスメトリック、機(jī)會、情報をリストする別のオブジェクトを含む監(jiān)査と呼ばれるプロパティがあります。ここには多くの情報がありますが、その多くはこのツールの目的のために興味がありません。

これは、比較したい9つのパフォーマンスメトリックの1つであるFirst Contentful Paintのエントリです。

 「ファーストコンテンツペイント」:{
  「ID」:「FirstContentful-Paint」、
  「タイトル」:「最初のコンテンツフルペイント」、
  「説明」:「最初のテキストまたは畫像がペイントされる時間を最初のコンテンツペイントマーク。[詳細(xì)](https://web.dev/first-contentful-paint)?!?  「スコア」:1
  「ScoredisPlayMode」:「數(shù)値」、
  「numericValue」:1081.661、
  「DisplayValue」:「1.1 s」
}

これらの9つのパフォーマンスメトリックのキーをリストする配列を作成します。これを使用して監(jiān)査オブジェクトをフィルタリングできます。

 const compareports =(from、to)=> {
  const metricfilter = [
    「ファーストコンテンツペイント」、
    「最初のことを意味するペイント」、
    「スピードインデックス」、
    「推定入力遅延」、
    「ブロッキングタイム全體」、
    「マックスポテンシャルフィッド」、
    「時間からの時間」、
    「First-CPU-Idle」、
    "相互の作用"
  ];
};

次に、レポートの監(jiān)査オブジェクトのいずれかをループし、その名前をフィルターリストに対して相互參照します。 (どちらの監(jiān)査オブジェクトが同じコンテンツ構(gòu)造を持っているため、どの監(jiān)査オブジェクトは関係ありません。)

それがそこにある場合、それから素晴らしい、私たちはそれを使いたいです。

 const metricfilter = [
  「ファーストコンテンツペイント」、
  「最初のことを意味するペイント」、
  「スピードインデックス」、
  「推定入力遅延」、
  「ブロッキングタイム全體」、
  「マックスポテンシャルフィッド」、
  「時間からの時間」、
  「First-CPU-Idle」、
  "相互の作用"
];

for(["audits"]からauditobjを入れてください){
  if(metricfilter.includes(auditobj)){
    console.log(auditobj);
  }
}

このConsole.log()は、以下のキーをコンソールに印刷します。

ファーストコンテンツペイント
最初のことを意味するペイント
Speed-Index
推定入力遅延
総ブロッキング時間
最大値 -  fid
最初の時間まで
First-CPU-Idle
相互の作用

つまり、['audits]] [auditobj] .numericvalueおよび[' audits '] [auditobj] [auditobj] .numericvalueにそれぞれ使用して、メトリック自體にアクセスすることを意味します。

これらをキーを使用してコンソールに印刷する場合、次のような出力になります。

 FirstContentful-Paint 1081.661 890.774
First-Minedful-Paint 1081.661 954.774
Speed-Index 15576.7031351777 1098.622294504341
推定入力遅延12.8 12.8
総ブロッキング時間59 31.5
Max-Potential-FID 153 102
16.8599999999985 16.09600000000000004
First-CPU-Idle 1704.8490000000002 1918.774
インタラクティブ2266.2835 2374.3615

必要なすべてのデータがあります。これら2つの値の割合の差を計算し、以前に概説したカラーコード形式の形式を使用してコンソールにログに記録するだけです。

2つの値間の変化率を計算する方法を知っていますか?私も。ありがたいことに、みんなのお気に入りのモノリス検索エンジンが救助に來ました。

式は次のとおりです。

 ((from -to) / from)x 100

したがって、最初のレポート(from)には5.7の速度インデックスがあり、次に2番目のレポート(to)で2.1秒の速度インデックスがあるとしましょう。計算は次のとおりです。

 5.7-2.1 = 3.6
3.6 / 5.7 = 0.63157895
0.63157895 * 100 = 63.157895

小數(shù)點以下の2つの場所に丸めると、速度指數(shù)が63.16%減少します。

これをMetricFilterアレイの下のComparEerports()関數(shù)內(nèi)のヘルパー関數(shù)に入れましょう。

 const calcpercentagediff =(from、to)=> {
  const per =((to --from) / from) * 100;
  return Math.round(per * 100) / 100;
};

Back in our auditObj conditional, we can begin to put together the final report comparison output.

First off, use the helper function to generate the percentage difference for each metric.

 for (let auditObj in from["audits"]) {
  if (metricFilter.includes(auditObj)) {
    const percentageDiff = calcPercentageDiff(
      from["audits"][auditObj].numericValue,
      to["audits"][auditObj].numericValue
    );
  }
}

Next, we need to output values in this format to the console:

This requires adding color to the console output. In Node.js, this can be done by passing a color code as an argument to the console.log() function like so:

 console.log('\x1b[36m', 'hello') // Would print 'hello' in cyan

You can get a full reference of color codes in this Stackoverflow question. We need green and red, so that's \x1b[32m and \x1b[31m respectively. For metrics where the value remains unchanged, we'll just use white. This would be \x1b[37m.

Depending on if the percentage increase is a positive or negative number, the following things need to happen:

  • Log color needs to change (Green for negative, red for positive, white for unchanged)
  • Log text contents change.
    • '[Name] is X% slower for positive numbers
    • '[Name] is X% faster' for negative numbers
    • '[Name] is unchanged' for numbers with no percentage difference.
  • If the number is negative, we want to remove the minus/negative symbol, as otherwise, you'd have a sentence like 'Speed Index is -92.95% faster' which doesn't make sense.

There are many ways this could be done. Here, we'll use theMath.sign() function, which returns 1 if its argument is positive, 0 if well… 0, and -1 if the number is negative. That'll do.

 for (let auditObj in from["audits"]) {
  if (metricFilter.includes(auditObj)) {
    const percentageDiff = calcPercentageDiff(
      from["audits"][auditObj].numericValue,
      to["audits"][auditObj].numericValue
    );

    let logColor = "\x1b[37m";
    const log = (() => {
      if (Math.sign(percentageDiff) === 1) {
        logColor = "\x1b[31m";
        return `${percentageDiff "%"} slower`;
      } else if (Math.sign(percentageDiff) === 0) {
        return "unchanged";
      } それ以外 {
        logColor = "\x1b[32m";
        return `${percentageDiff "%"} faster`;
      }
    })();
    console.log(logColor, `${from["audits"][auditObj].title} is ${log}`);
  }
}

So, there we have it.

You can create new Lighthouse reports, and if a previous one exists, a comparison is made.

And you can also compare any two reports from any two sites.

Complete source code

Here's the completed source code for the tool, which you can also view in a Gist via the link below.

 const lighthouse = require("lighthouse");
const chromeLauncher = require("chrome-launcher");
const argv = require("yargs").argv;
const url = require("url");
const fs = require("fs");
const glob = require("glob");
const path = require("path");

const launchChromeAndRunLighthouse = url => {
  return chromeLauncher.launch().then(chrome => {
    const opts = {
      port: chrome.port
    };
    return lighthouse(url, opts).then(results => {
      return chrome.kill().then(() => {
        戻る {
          js: results.lhr,
          json: results.report
        };
      });
    });
  });
};

const getContents = pathStr => {
  const output = fs.readFileSync(pathStr, "utf8", (err, results) => {
    return results;
  });
  return JSON.parse(output);
};

const compareReports = (from, to) => {
  const metricFilter = [
    "first-contentful-paint",
    "first-meaningful-paint",
    "speed-index",
    "estimated-input-latency",
    "total-blocking-time",
    "max-potential-fid",
    "time-to-first-byte",
    "first-cpu-idle",
    "相互の作用"
  ];

  const calcPercentageDiff = (from, to) => {
    const per = ((to - from) / from) * 100;
    return Math.round(per * 100) / 100;
  };

  for (let auditObj in from["audits"]) {
    if (metricFilter.includes(auditObj)) {
      const percentageDiff = calcPercentageDiff(
        from["audits"][auditObj].numericValue,
        to["audits"][auditObj].numericValue
      );

      let logColor = "\x1b[37m";
      const log = (() => {
        if (Math.sign(percentageDiff) === 1) {
          logColor = "\x1b[31m";
          return `${percentageDiff.toString().replace("-", "") "%"} slower`;
        } else if (Math.sign(percentageDiff) === 0) {
          return "unchanged";
        } それ以外 {
          logColor = "\x1b[32m";
          return `${percentageDiff.toString().replace("-", "") "%"} faster`;
        }
      })();
      console.log(logColor, `${from["audits"][auditObj].title} is ${log}`);
    }
  }
};

if (argv.from && argv.to) {
  compareReports(
    getContents(argv.from ".json"),
    getContents(argv.to ".json")
  );
} else if (argv.url) {
  const urlObj = new URL(argv.url);
  let dirName = urlObj.host.replace("www.", "");
  if (urlObj.pathname !== "/") {
    dirName = dirName urlObj.pathname.replace(/\//g, "_");
  }

  if (!fs.existsSync(dirName)) {
    fs.mkdirSync(dirName);
  }

  launchChromeAndRunLighthouse(argv.url).then(results => {
    const prevReports = glob(`${dirName}/*.json`, {
      sync: true
    });

    if (prevReports.length) {
      dates = [];
      for (report in prevReports) {
        dates.push(
          new Date(path.parse(prevReports[report]).name.replace(/_/g, ":"))
        );
      }
      const max = dates.reduce(function(a, b) {
        return Math.max(a, b);
      });
      const recentReport = new Date(max).toISOString();

      const recentReportContents = getContents(
        dirName "/" recentReport.replace(/:/g, "_") ".json"
      );

      compareReports(recentReportContents, results.js);
    }

    fs.writeFile(
      `${dirName}/${results.js["fetchTime"].replace(/:/g, "_")}.json`,
      results.json,
      err => {
        (err)スローERR;
      }
    );
  });
} それ以外 {
  throw "You haven't passed a URL to Lighthouse";
}

View Gist

Next steps

With the completion of this basic Google Lighthouse tool, there's plenty of ways to develop it further.例えば:

  • Some kind of simple online dashboard that allows non-technical users to run Lighthouse audits and view metrics develop over time. Getting stakeholders behind web performance can be challenging, so something tangible they can interest with themselves could pique their interest.
  • Build support for performance budgets, so if a report is generated and performance metrics are slower than they should be, then the tool outputs useful advice on how to improve them (or calls you names).

幸運(yùn)を!

以上がnode.jsツールを作成して、Google Lighthouseレポートを記録および比較するの詳細(xì)內(nèi)容です。詳細(xì)については、PHP 中國語 Web サイトの他の関連記事を參照してください。

このウェブサイトの聲明
この記事の內(nèi)容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰屬します。このサイトは、それに相當(dāng)する法的責(zé)任を負(fù)いません。盜作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡(luò)ください。

ホットAIツール

Undress AI Tool

Undress AI Tool

脫衣畫像を無料で

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード寫真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

寫真から衣服を削除するオンライン AI ツール。

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中國語版

SublimeText3 中國語版

中國語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強(qiáng)力な PHP 統(tǒng)合開発環(huán)境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

「レンダリングブロッキングCSS」とは何ですか? 「レンダリングブロッキングCSS」とは何ですか? Jun 24, 2025 am 12:42 AM

ブラウザは、特にインポートされたスタイルシート、ヘッダーのインラインCSS、および最適化されていないメディアクエリスタイルを使用して、ブラウザがインラインおよび外部CSSをデフォルトで主要なリソースとして表示するため、ページレンダリングをブロックします。 1.重要なCSSを抽出し、HTMLに埋め込みます。 2。JavaScriptを介して非クリティカルなCSSの読み込みを遅らせる。 3.メディア屬性を使用して、印刷スタイルなどのロードを最適化します。 4.リクエストを減らすためにCSSを圧縮およびマージします。ツールを使用してキーCSSを抽出し、REL = "Preload"非同期負(fù)荷を組み合わせ、過度の分割と複雑なスクリプト制御を避けるためにメディア遅延荷重を合理的に使用することをお勧めします。

外部対內(nèi)部CSS:最良のアプローチは何ですか? 外部対內(nèi)部CSS:最良のアプローチは何ですか? Jun 20, 2025 am 12:45 AM

TheBestAppRoachforCSDependsonTheProject'sSpecificNeeds.forLargerProjects、externalCssissisbetterduetoMaintainasiladability; forsmallerProjectsOrsingLe-PageApplications、internalcsSmightBemoresuitable.it

私のCSSは小文字でなければなりませんか? 私のCSSは小文字でなければなりませんか? Jun 19, 2025 am 12:29 AM

いいえ、CSSDOESNOTHAVETOBEINLOWERCASE。

CSSケース感度:重要なことを理解する CSSケース感度:重要なことを理解する Jun 20, 2025 am 12:09 AM

cssismostlycase-inssensitive、buturlsandfontfamilynamesarecase-sensitive.1)propertiesandvalueslikecolor:red; areotcase-sensitive.2)urlsmustmatchtheserver'scase、例えば、/畫像/logo.png.3)

Autoprefixerとは何ですか?それはどのように機(jī)能しますか? Autoprefixerとは何ですか?それはどのように機(jī)能しますか? Jul 02, 2025 am 01:15 AM

Autoprefixerは、ターゲットブラウザスコープに基づいてCSS屬性にベンダープレフィックスを自動的に追加するツールです。 1.エラーで接頭辭を手動で維持する問題を解決します。 2. PostCSSプラグインフォーム、CSSを解析し、プレフィックスする必要がある屬性を分析し、構(gòu)成に従ってコードを生成する屬性を分析します。 3.使用手順には、プラグインのインストール、ブラウザーリストの設(shè)定、ビルドプロセスでそれらを有効にすることが含まれます。 4。メモには、接頭辭を手動で追加しない、構(gòu)成の更新を保持すること、すべての屬性ではなくプレフィックスを維持することが含まれ、プリ??プロセッサでそれらを使用することをお勧めします。

CSSカウンターとは何ですか? CSSカウンターとは何ですか? Jun 19, 2025 am 12:34 AM

csScountersCantAnationally-bersectionSandLists.1)usecounter-resettoinitialize、counter-incrementtoincrease、andcounter()orcounters()todisplayvalues.2)を組み合わせたjavascriptfordynamiccontenttoensureaCurateupdatesと組み合わせます。

CSS:ケースはいつ重要ですか(いつそうではありませんか)? CSS:ケースはいつ重要ですか(いつそうではありませんか)? Jun 19, 2025 am 12:27 AM

CSSでは、セレクターと屬性名はケースに敏感ですが、値、名前の色、URL、およびカスタム屬性はケースに敏感です。 1.バックグラウンドカラーや背景色など、セレクターと屬性名はケース非感受性です。 2。値の16進(jìn)數(shù)色は大文字と小文字を區(qū)別しますが、赤と赤などの名前の色は無効です。 3. URLは癥例に敏感であり、ファイルロードの問題を引き起こす可能性があります。 4.カスタムプロパティ(変數(shù))はケースに敏感であり、使用する場合はケースの一貫性に注意を払う必要があります。

conic-gradient()関數(shù)とは何ですか? conic-gradient()関數(shù)とは何ですか? Jul 01, 2025 am 01:16 AM

TheConic-Gradient()functionsscreateScular勾配の勾配は、測定されていることを確認(rèn)してください

See all articles