이 튜토리얼에서는 Node.js에서 간단한 도구를 작성하여 명령 줄을 통해 Google Lighthouse Audits를 실행하고 JSON 형식으로 생성 된 보고서를 저장 한 다음 웹 사이트가 성장하고 발전함에 따라 웹 성능을 모니터링 할 수 있도록 비교하는 방법을 단계별로 보여 드리겠습니다.
나는 이것이 Google Lighthouse와 프로그래밍 방식으로 일하는 방법에 대해 배우는 데 관심이있는 개발자에게 좋은 소개 역할을 할 수 있기를 바랍니다.
그러나 먼저, 초기에…
Google Lighthouse는 무엇입니까?
Google Lighthouse는 웹 개발자의 유틸리티 벨트에서 사용할 수있는 최고의 오토로 만든 도구 중 하나입니다. 이를 통해 여러 주요 영역에서 웹 사이트를 빠르게 감사 할 수 있으며, 이는 전체 품질의 측정을 형성 할 수 있습니다. 이들은 다음과 같습니다.
- 성능
- 접근성
- 모범 사례
- 서
- 프로그레시브 웹 앱
감사가 완료되면 웹 사이트가 잘하는 일에 대한 보고서가 생성됩니다. 후자는 다음 단계가 페이지를 개선하기위한 다음 단계에 대한 지표 역할을하려고합니다.
다음은 전체 보고서의 모습입니다.
다른 일반 진단 및 웹 성능 메트릭과 함께 보고서의 매우 유용한 기능은 각 주요 영역이 0-100 사이의 색상으로 구성된 점수로 집계된다는 것입니다.
이를 통해 개발자는 추가 분석없이 웹 사이트의 품질을 빠르게 측정 할 수있을뿐만 아니라 이해 관계자 나 고객과 같은 비 기술적 인 사람들도 이해할 수 있습니다.
예를 들어, 이는 등대 접근성 점수가 50 점을 녹색으로 올라가는 것을보고 노력에 더 감사 할 수 있기 때문에 웹 사이트 접근성을 개선하는 데 시간을 소비 한 후 마케팅에서 Heather와의 승리를 공유하는 것이 훨씬 쉽다는 것을 의미합니다.
그러나 프로젝트 관리자 Simon은 속도 지수 또는 첫 번째 콘텐츠 페인트가 무엇을 의미하는지 이해하지 못할 수도 있지만, 웹 사이트 성능 점수가 빨간색으로 깊숙이 무릎을 꿇는 등대 보고서를 볼 때 여전히해야 할 일이 있다는 것을 알고 있습니다.
Chrome 또는 최신 버전의 Edge에 있다면 DevTools를 사용하여 지금 직접 등대 감사를 실행할 수 있습니다. 방법은 다음과 같습니다.
또한 Pagespeed Insights 또는 WebPagetest와 같은 인기있는 성능 도구를 통해 온라인으로 Lighthouse 감사를 실행할 수도 있습니다.
그러나 오늘날 우리는 Lighthouse에 Node 모듈로 만 관심이 있습니다.이를 통해 프로그래밍 방식으로 도구를 사용하여 웹 성능 메트릭을 감사, 기록 및 비교할 수 있습니다.
방법을 알아 봅시다.
설정
먼저, 아직 가지고 있지 않으면 node.js가 필요합니다. 설치하는 방법에는 백만 가지가 있습니다. Homebrew Package Manager를 사용하지만 선호하는 경우 Node.js 웹 사이트에서 바로 설치자를 다운로드 할 수도 있습니다.이 자습서는 Node.js v10.17.0을 염두에두고 작성되었지만 지난 몇 년 동안 출시 된 대부분의 버전에서는 잘 작동합니다.
또한 Lighthouse 감사를 실행하는 방식이므로 Chrome 설치가 필요합니다.
다음으로 프로젝트에 대한 새 디렉토리를 작성한 다음 콘솔에서 CD를 CD에 넣으십시오. 그런 다음 npm init를 실행하여 package.json 파일을 만들기 시작합니다. 이 시점에서 파일이 생성 될 때까지 가능한 한 많은 것을 건너 뛰기 위해 Enter 키를 계속해서 강타하는 것이 좋습니다.
이제 프로젝트 디렉토리에서 새 파일을 만들어 봅시다. 나는 내 lh.js에 전화했지만 당신이 원하는 것을 자유롭게 부르십시오. 여기에는 도구에 대한 모든 JavaScript가 포함됩니다. 선택의 텍스트 편집기에서 열고 지금은 Console.log 문을 작성하십시오.
Console.log ( 'Hello World');
그런 다음 콘솔에서 CWD (현재 작업 디렉토리)가 프로젝트 디렉토리이고 Node LH.JS를 실행하여 내 파일 이름을 사용한 내용으로 대체하십시오.
당신은 볼 수 있어야합니다 :
$ 노드 lh.js 안녕하세요 세계
그렇지 않은 경우 노드 설치가 작동하는지 확인하고 정확한 프로젝트 디렉토리에 있습니다.
이제는 도구 자체를 개발할 수 있습니다.
node.js로 크롬을 여는 것
프로젝트의 첫 번째 의존성 인 등대 자체를 설치합시다.
NPM Lighthouse 설치 -Save-Dev
이것은 패키지의 모든 파일을 포함하는 node_modules 디렉토리를 만듭니다. git을 사용하는 경우 이것으로하고 싶은 유일한 일은 .gitignore 파일에 추가하는 것입니다.
LH.JS에서는 다음에 테스트 콘솔을 삭제하고 Lighthouse 모듈을 가져와 코드에서 사용할 수 있도록합니다. 그렇게 :
Const Lighthouse = 요구 사항 ( 'Lighthouse');
아래에서는 Lighthouse의 종속성 중 하나 인 Chrome-Launcher라는 모듈을 가져와야하며 Node가 Chrome 자체를 시작하여 감사를 실행할 수 있습니다.
Const Lighthouse = 요구 사항 ( 'Lighthouse'); const chromelauncher = 요구 사항 ( 'Chrome-Launcher');
이제이 두 모듈에 액세스 할 수있게되었으므로 크롬을 열고 등대 감사를 실행 한 다음 보고서를 콘솔에 인쇄하는 간단한 스크립트를 작성하겠습니다.
URL을 매개 변수로 받아들이는 새 기능을 만듭니다. Node.js를 사용 하여이 작업을 실행하므로 성가신 인터넷 익스플로러 사용자에 대해 걱정할 필요가 없으므로 ES6 구문을 안전하게 사용할 수 있습니다.
const launchchrome = (url) => { }
이 기능 내에서 가장 먼저해야 할 일은 가져온 크롬 출시자 모듈을 사용하여 Chrome을 열고 URL 매개 변수를 통해 전달되는 인수로 전송하는 것입니다.
런치 () 메소드와 STARTINES 옵션을 사용하여이를 수행 할 수 있습니다.
const launchchrome = url => { Chromelauncher.launch ({{ starithurl : url }); };
아래 기능을 호출하고 선택의 URL을 전달하면 노드 스크립트가 실행될 때 Chrome이 URL에서 열립니다.
LaunchChrome ( 'https://www.lukeharrison.dev');
실행 함수는 실제로 약속을 반환하여 몇 가지 유용한 방법과 속성이 포함 된 객체에 액세스 할 수 있습니다.
예를 들어, 아래 코드를 사용하여 Chrome을 열고 콘솔에 객체를 인쇄 한 다음 Kill () 메소드를 사용하여 3 초 후에 Chrome을 닫을 수 있습니다.
const launchchrome = url => { Chromelauncher .시작하다({ starithurl : url }) . 그런데 (chrome => { Console.log (Chrome); settimeout (() => chrome.kill (), 3000); }); }; LaunchChrome ( "https://www.lukeharrison.dev");
이제 우리가 Chrome을 알아 냈으므로 Lighthouse로 넘어 갑시다.
프로그래밍 방식으로 등대를 운영합니다
먼저, LaunchChrome () 함수의 최종 기능을 더 반영한 것으로 바꾸겠습니다. 어려운 부분을 벗어나면서 우리는 이제 튜토리얼에서 앞서 가져온 등대 모듈을 사용할 수 있습니다.
크롬 발사기의 기능에서 브라우저가 열린 후에 만 실행되는 기능에서는 Lighthouse에 기능의 URL 인수를 전달 하고이 웹 사이트의 감사를 트리거합니다.
const uncl uncondromeandrunlighthouse = url => { Chromelauncher .시작하다({ starithurl : url }) . 그런데 (chrome => { const opts = { 포트 : Chrome.port }; 등대 (URL, OPTS); }); }; LaunchChromeAndrunlighthouse ( "https://www.lukeharrison.dev");
Lighthouse 인스턴스를 Chrome 브라우저 창에 연결하려면 URL과 함께 포트를 전달해야합니다.
지금이 스크립트를 실행하려면 콘솔에서 오류가 발생합니다.
(Node : 47714) UnhandledPromisere deceditewarning : 오류 : 동일한 원점에 여러 개의 탭이 열려있을 수 있습니다.
이 문제를 해결하려면 Chrome Launcher에서 SarthingUrl 옵션을 제거하고 Lighthouse가 URL 내비게이션을 여기에서 처리해야합니다.
const uncl uncondromeandrunlighthouse = url => { Chromelauncher.launch (). 그런 다음 (Chrome => { const opts = { 포트 : Chrome.port }; 등대 (URL, OPTS); }); };
이 코드를 실행하려면 무언가가 일어나고있는 것 같습니다. 우리는 콘솔에서 등대 감사가 확실히 실행되었는지 확인하기 위해 피드백을받지 못하고 Chrome 인스턴스가 이전과 마찬가지로 닫히지 않습니다.
고맙게도 Lighthouse () 함수는 우리가 감사 결과에 액세스 할 수있는 약속을 반환합니다.
크롬을 죽인 다음 결과 객체의 보고서 특성을 통해 그 결과를 JSON 형식의 터미널에 인쇄합시다.
const uncl uncondromeandrunlighthouse = url => { Chromelauncher.launch (). 그런 다음 (Chrome => { const opts = { 포트 : Chrome.port }; 등대 (URL, OPTS). Chrome.kill (); Console.log (results.report); }); }); };
콘솔이 이러한 결과를 표시하는 가장 좋은 방법은 아니지만 클립 보드에 복사하여 Lighthouse Report Viewer를 방문하려면 여기에 붙여 넣기는 모든 영광으로 보고서를 표시합니다.
이 시점에서 런치를 약간 정리하기 위해 코드를 조금 정리하는 것이 중요합니다. 이를 통해 우리는 JavaScript의 지저분한 피라미드를 초래하지 않고 나중에 보고서를 처리 할 수 있습니다.
Const Lighthouse = 요구 사항 ( "Lighthouse"); const chromelauncher = 요구 사항 ( "Chrome-Launcher"); const uncl uncondromeandrunlighthouse = url => { chromelauncher.launch (). 그런 다음 (chrome => { const opts = { 포트 : Chrome.port }; 리턴 등대 (URL, OPTS). chrome.kill (). 그런 다음 (() => results.report); }); }); }; 런치를 lainkchromeandrunlighthouse ( "https://www.lukeharrison.dev"). (results => { Console.log (결과); });
당신이 알아 차린 한 가지는 우리의 도구가 현재 단일 웹 사이트 만 감사 할 수 있다는 것입니다. 명령 줄을 통해 인수로 URL을 전달할 수 있도록 이것을 변경합시다.
명령 줄 인수로 작업하는 데 어려움을 겪으려면 Yargs라는 패키지로 처리 할 것입니다.
NPM 설치-사브 데브 yargs
그런 다음 크롬 발사기 및 등대와 함께 스크립트 상단에서 가져 오십시오. 여기서는 ArgV 기능 만 필요합니다.
Const Lighthouse = 요구 사항 ( 'Lighthouse'); const chromelauncher = 요구 사항 ( 'Chrome-Launcher'); const argv = 요구 ( 'yargs'). argv;
이것은 당신이 다음과 같은 터미널에서 명령 줄 인수를 통과해야한다는 것을 의미합니다.
노드 lh.js --url https://www.google.co.uk
… 그런 것과 같은 스크립트의 인수에 액세스 할 수 있습니다.
const url = argv.url // https://www.google.co.uk
스크립트를 편집하여 명령 행 URL 인수를 함수의 URL 매개 변수로 전달해 봅시다. 인수가 전달되지 않은 경우 IF 문 및 오류 메시지를 통해 약간의 안전망을 추가하는 것이 중요합니다.
if (argv.url) { LaunchChromeAndrunlighthouse (argv.url). (results => { Console.log (결과); }); } 또 다른 { "당신은 등대에 URL을 통과하지 못했습니다"; }
타다! Chrome을 시작하고 JSON 형식의 터미널에 보고서를 인쇄하기 전에 크롬을 시작하고 등대 감사를 실행하는 도구가 있습니다.
등대 저장 보고서
콘솔에 보고서를 인쇄하는 것은 내용물을 쉽게 읽을 수 없기 때문에 유용하지 않으며 향후 사용을 위해 저장되지도 않습니다. 튜토리얼 의이 섹션에서는이 동작을 변경하여 각 보고서가 자체 JSON 파일에 저장됩니다.
다른 웹 사이트의 보고서가 혼합되어 보고서를 중단하기 위해 우리는 다음과 같이 구성 할 것입니다.
- 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
보고서의 이름은 보고서가 생성 된 날짜/시간을 나타내는 타임 스탬프로 이름을 지정합니다. 이는 두 개의 보고서 파일 이름이 동일하지 않으며 보고서를 쉽게 구별하는 데 도움이 될 것입니다.
Windows에는 우리의 관심이 필요한 한 가지 문제가 있습니다. 콜론 (:)는 파일 이름의 불법적 인 문자입니다. 이 문제를 완화하기 위해 콜을 밑줄 (_)으로 교체하므로 일반적인 보고서 파일 이름은 다음과 같습니다.
- 2020-01-31T18_18_12.648Z.JSON
디렉토리 생성
먼저, 디렉토리 이름에 사용할 수 있도록 명령 줄 URL 인수를 조작해야합니다.
여기에는 www를 제거하는 것 이상의 것이 포함됩니다. 루트에 앉아 있지 않은 웹 페이지에서 실행되는 감사를 설명해야합니다 (예 : www.foo.com/bar). 슬래시는 디렉토리 이름의 유효하지 않은 문자이므로.
이 URL의 경우 유효하지 않은 문자를 밑줄로 교체합니다. 이렇게하면 https://www.foo.com/bar에서 감사를 실행하면 보고서가 포함 된 결과 디렉토리 이름은 foo.com_bar입니다.
URL을보다 쉽게 처리하기 위해 URL이라는 기본 Node.js 모듈을 사용합니다. 이것은 다른 패키지와 마찬가지로 가져올 수 있으며 thepackage.json에 추가하지 않고도 NPM을 통해 당기지 않아도됩니다.
Const Lighthouse = 요구 사항 ( 'Lighthouse'); const chromelauncher = 요구 사항 ( 'Chrome-Launcher'); const argv = 요구 ( 'yargs'). argv; const url = 요구 사항 ( 'url');
다음으로 새 URL 객체를 인스턴스화하는 데 사용해 봅시다.
if (argv.url) { const urlobj = new URL (argv.url); LaunchChromeAndrunlighthouse (argv.url). (results => { Console.log (결과); }); }
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', 포트 : '', PathName : '/bar', 찾다: '', SearchParams : urlsearchparams {}, 해시 : '' }
Dirname이라는 새 변수를 작성하고 URL의 호스트 속성에있는 String Replace () 메소드를 사용하여 https 프로토콜 외에도 www를 제거하십시오.
const urlobj = new URL (argv.url); dirname = urlobj.host.replace ( 'www.', '');
우리는 let here를 사용했는데, Const와 달리 재 할당 할 수 있습니다. URL에 PathName이 있으면 슬래시를 밑줄로 바꾸려면 참조를 업데이트해야하므로 참조를 업데이트해야합니다. 이것은 정규 표현 패턴으로 수행 할 수 있으며 다음과 같습니다.
const urlobj = new URL (argv.url); dirname = urlobj.host.replace ( "www.", ""); if (urlobj.pathname! == "/") { dirname = dirname urlobj.pathname.replace (/\ // g, "_"); }
이제 디렉토리 자체를 만들 수 있습니다. 이는 FS ( "파일 시스템"의 경우 짧음)라는 다른 기본 Node.js 모듈을 사용하여 수행 할 수 있습니다.
Const Lighthouse = 요구 사항 ( 'Lighthouse'); const chromelauncher = 요구 사항 ( 'Chrome-Launcher'); const argv = 요구 ( 'yargs'). argv; const url = 요구 사항 ( 'url'); const fs = 요구 사항 ( 'fs');
mkdir () 메소드를 사용하여 디렉토리를 만들 수 있지만, 먼저 Node.js가 오류를 던질 수 있으므로 디렉토리가 이미 존재하는지 확인하기 위해 ensistSync () 메소드를 사용해야합니다.
const urlobj = new URL (argv.url); dirname = urlobj.host.replace ( "www.", ""); if (urlobj.pathname! == "/") { dirname = dirname urlobj.pathname.replace (/\ // g, "_"); } if (! fs.existsSync (dirname)) { fs.mkdirsync (dirname); }
지점에서 스크립트를 테스트하면 새 디렉토리가 생성됩니다. URL 인수로 https://www.bbc.co.uk/news를 통과하면 bbc.co.uk_news라는 디렉토리가 생길 수 있습니다.
보고서 저장
LaunchChromeAndrunLighThouse ()의 기능에서는 기존 콘솔을 논리로 교체하여 보고서를 디스크에 작성하려고합니다. FS Module의 writeFile () 메소드를 사용하여 수행 할 수 있습니다.
LaunchChromeAndrunlighthouse (argv.url). (results => { fs.writefile ( "report.json", results, err => { (err)를 던지면; }); });
첫 번째 매개 변수는 파일 이름을 나타내고, 두 번째는 파일의 내용이고 세 번째는 쓰기 프로세스 중에 무언가 잘못되면 오류 객체를 포함하는 콜백입니다. 이로 인해 리턴 등대 보고서 JSON 개체가 포함 된 report.json이라는 새 파일이 생성됩니다.
우리는 여전히 파일 이름으로 타임 스탬프를 사용하여 올바른 디렉토리로 보내야합니다. 전자는 간단합니다.
LaunchChromeAndrunlighthouse (argv.url). (results => { fs.writefile (`$ {dirname}/report.json`, 결과, err => { (err)를 던지면; }); });
후자는 보고서가 생성 된 시점의 타임 스탬프를 어떻게 든 검색해야합니다. 고맙게도 보고서 자체는이를 데이터 포인트로 캡처하고 FetchTime 속성으로 저장됩니다.
우리는 콜론 (:) 밑줄 (_)을 위해 콜론을 교체해야한다는 것을 기억하면 Windows 파일 시스템과 잘 어울립니다.
LaunchChromeAndrunlighthouse (argv.url). (results => { fs.writefile ( `$ {dirname}/$ {results [ "fetchtime"]. Replace (/:/g, "_")}. 결과, err => { (err)를 던지면; } ); });
timestamped.json filename 대신 지금 이것을 실행한다면 다음과 비슷한 오류가 표시 될 수 있습니다.
UnhandledPromisereEdugeWarning : TypeError : 정의되지 않은 속성을 읽을 수 없습니다
Lighthouse가 현재 JavaScript가 소모 할 수있는 객체가 아닌 JSON 형식으로 보고서를 반환하고 있기 때문에 이런 일이 발생합니다.
고맙게도, JSON을 직접 구문 분석하는 대신, 우리는 Lighthouse에게 보고서를 일반 JavaScript 객체로 반환하도록 요청할 수 있습니다.
아래 줄을 편집해야합니다.
chrome.kill (). 그런 다음 (() => results.report);
…에게:
chrome.kill (). 그런 다음 (() => results.lhr);
이제 스크립트를 다시 실행하면 파일의 이름이 올바르게 지정됩니다. 그러나 열면 불행히도 콘텐츠만이 될 것입니다 ...
[개체 객체]
우리는 이제 우리가 이전과 같이 반대의 문제를 겪었 기 때문입니다. 우리는 먼저 JSON 객체로 연결하지 않고 JavaScript 객체를 렌더링하려고합니다.
솔루션은 간단합니다. 이 거대한 물체를 구문 분석하거나 구매할 때 자원을 낭비하지 않도록하기 위해 Lighthouse에서 두 가지 유형을 모두 반환 할 수 있습니다.
리턴 등대 (URL, OPTS). chrome.kill (). 그런 다음 (() => {리턴 반품 { JS : 결과 .LHR, JSON : 결과.보고 }; }); });
그런 다음 writefile 인스턴스를 이것으로 수정할 수 있습니다.
fs.writefile ( `$ {dirname}/$ {results.js [ "fetchtime"]. choply (/:/g, "_"). json`, json`, results.json, err => { (err)를 던지면; } );
정렬! Lighthouse Audit이 완료되면 우리의 도구는 이제 웹 사이트 URL의 이름을 딴 디렉토리의 고유 한 타임 스탬프 파일 이름이있는 파일에 보고서를 저장해야합니다.
이는 보고서가 이제 훨씬 더 효율적으로 구성되어 있으며 얼마나 많은 보고서를 저장하든 서로를 대체하지 않을 것입니다.
등대 보고서 비교
일상적인 개발 중에 성능 향상에 중점을두면 콘솔에서 보고서를 매우 빠르게 비교하고 올바른 방향으로 향하는지 확인하는 기능이 매우 유용 할 수 있습니다. 이를 염두에 두고이 비교 기능의 요구 사항은 다음과 같습니다.
- 등대 감사가 완료되면 동일한 웹 사이트에 대해 이전 보고서가 이미 존재하는 경우 자동으로 비교를 수행하고 주요 성능 메트릭에 대한 변경 사항을 표시하십시오.
- 또한 필요하지 않은 새로운 등대 보고서를 생성 할 필요없이 두 웹 사이트의 두 보고서의 주요 성능 메트릭을 비교할 수 있어야합니다.
보고서의 어떤 부분을 비교해야합니까? 이들은 등대 보고서의 일부로 수집 된 숫자 주요 성능 지표입니다. 그들은 웹 사이트의 객관적이고인지 된 성능에 대한 통찰력을 제공합니다.
또한 Lighthouse는 보고서 의이 부분에 나열되지는 않지만 여전히 비교에 포함될 적절한 형식입니다. 이들은 다음과 같습니다.
- 첫 바이트까지 - 첫 바이트까지의 시간은 서버가 응답을 보내는 시간을 식별합니다.
- 총 차단 시간 - 작업 길이가 50ms를 초과 할 때 FCP와 대화식 시간 사이의 모든 시간의 합계는 밀리 초로 표현됩니다.
- 추정 입력 대기 시간 - 추정 입력 대기 시간은 가장 바쁜 5s 페이지로드 기간 동안 앱이 밀리 초로 사용자 입력에 응답하는 데 걸리는 시간을 추정하는 것입니다. 대기 시간이 50ms보다 높으면 사용자는 앱을 더 느린 것으로 인식 할 수 있습니다.
메트릭 비교는 어떻게 콘솔에 출력해야합니까? 구식 및 새로운 메트릭을 사용하여 간단한 백분율 기반 비교를 만들어 보고서에서 보고서로 어떻게 변경되었는지 확인합니다.
빠른 스캔을 허용하기 위해 더 빠르거나 느리거나 변하지 않은지에 따라 개별 메트릭을 색상 코딩합니다.
우리는이 출력을 목표로합니다.
이전 보고서와 새로운 보고서를 비교하십시오
모든 비교 로직을 포함하는 LaunchChromeAndrunLighThouse () 함수 바로 아래에있는 comparePorports ()라는 새로운 함수를 만들어 시작하겠습니다. 우리는 비교에 사용 된 두 가지 보고서를 수락하기 위해 두 가지 매개 변수를 제공합니다.
현재 자리 표시자는 각 보고서에서 콘솔에 일부 데이터를 인쇄하여 올바르게 수신하고 있는지 확인합니다.
const compraleReports = (from, to) => { Console.log ([ "FinalUrl"] "" "에서 ["FetchTime "]); console.log ([ "finalUrl"] ""to [ "fetchTime"]); };
이 비교가 새로운 보고서를 작성한 후에 시작되면이 기능을 실행하는 논리는 LaunchChromeAndrunLighThouse ()의 기능에 앉아 있어야합니다.
예를 들어, 디렉토리에 30 개의 보고서가있는 경우 가장 최근의 보고서를 결정하고 새로운 보고서가 새로운 보고서를 비교할 이전 보고서로 설정해야합니다. 고맙게도, 우리는 이미 타임 스탬프를 보고서의 파일 이름으로 사용하기로 결정했기 때문에 우리와 함께 일할 것을 제공합니다.
먼저 기존 보고서를 수집해야합니다. 이 프로세스를 쉽게하기 위해 Glob라는 새로운 의존성을 설치하여 파일을 검색 할 때 패턴 일치가 가능합니다. 얼마나 많은 보고서가 존재하는지 또는 그 부름을받을 보고서를 예측할 수 없기 때문에 이것은 중요합니다.
다른 종속성처럼 설치하십시오.
NPM 설치 glob-save-dev
그런 다음 평소와 같은 방식으로 파일 상단에서 가져옵니다.
Const Lighthouse = 요구 사항 ( 'Lighthouse'); const chromelauncher = 요구 사항 ( 'Chrome-Launcher'); const argv = 요구 ( 'yargs'). argv; const url = 요구 사항 ( 'url'); const fs = 요구 사항 ( 'fs'); Const Glob = 요구 사항 ( 'glob');
우리는 디렉토리에서 모든 보고서를 수집하기 위해 Glob을 사용하여 이미 Dirname 변수의 이름을 알고 있습니다. 다른 보고서가 얼마나 많은지 알 때까지 JavaScript 실행이 계속되기를 원하지 않으므로 SYNC 옵션을 True로 설정하는 것이 중요합니다.
LaunchChromeAndrunlighthouse (argv.url). (results => { const prevreports = glob (`$ {dirname}/*. json`, { 동기화 : true }); // et al });
이 프로세스는 다양한 경로를 반환합니다. 따라서 보고서 디렉토리가 다음과 같습니다.
- Lukeharrison.dev
- 2020-01-31T10_18_12.648Z.JSON
- 2020-01-31T10_18_24.110Z.JSON
… 그런 다음 결과 배열이 다음과 같습니다.
[의 뜻 'Lukeharrison.dev/2020-01-31T10_18_12.648Z.json', 'Lukeharrison.dev/2020-01-31T10_18_24.110Z.json' ]]
이전 보고서가 존재하는 경우에만 비교를 수행 할 수 있으므로이 배열을 비교 논리의 조건부로 사용하겠습니다.
const prevreports = glob (`$ {dirname}/*. json`, { 동기화 : true }); if (prevreports.length) { }
보고서 파일 경로 목록이 있으며 가장 최근의 파일 이름을 결정하기 위해 타임 스탬프 파일 이름을 비교해야합니다.
즉, 먼저 모든 파일 이름 목록을 수집하고 디렉토리 이름과 같은 관련없는 데이터를 다듬고 밑줄 (_)을 콜론으로 대체하여 다시 유효한 날짜로 전환해야합니다. 이 작업을 수행하는 가장 쉬운 방법은 다른 Node.js 기본 모듈 인 Path를 사용하는 것입니다.
const path = 요구 ( '경로');
그렇게하는 방법에 대한 논쟁으로 경로를 전달합니다.
PATH.PARSE ( 'lukeharrison.dev/2020-01-31T10_18_24.110Z.json');
이 유용한 개체를 반환합니다.
{ 루트 : '', dir : 'lukeharrison.dev', 기본 : '2020-01-31T10_18_24.110Z.json', 내선 : '.json', 이름 : '2020-01-31T10_18_24.110Z' }
따라서 모든 타임 스탬프 파일 이름의 목록을 얻으려면 다음을 수행 할 수 있습니다.
if (prevreports.length) { 날짜 = []; for (prevreports에서보고) { 날짜. 새 날짜 (path.parse (prevreports [report]). name.replace (/_/g, ":")) ); } }
디렉토리가 다시 보이면 다시
- Lukeharrison.dev
- 2020-01-31T10_18_12.648Z.JSON
- 2020-01-31T10_18_24.110Z.JSON
결과를 초래할 것입니다.
[의 뜻 '2020-01-31T10 : 18 : 12.648Z', '2020-01-31T10 : 18 : 24.110Z' ]]
날짜에 대한 유용한 점은 기본적으로 본질적으로 비교할 수 있다는 것입니다.
const alpha = 새로운 날짜 ( '2020-01-31'); Const Bravo = 새로운 날짜 ( '2020-02-15'); Console.log (alpha> bravo); // 거짓 Console.log (Bravo> Alpha); // 진실
따라서 감소 기능을 사용하면 가장 최근의 남아있을 때까지 날짜 배열을 줄일 수 있습니다.
날짜 = []; for (prevreports에서보고) { Dates.Push (새 날짜 (path.parse (prevreports [report]). name.replace (/_/g, ":")); } const max = dates.reduce (function (a, b) { return math.max (a, b); });
Max의 내용을 콘솔에 인쇄한다면 Unix 타임 스탬프가 발생하므로 이제 가장 최근 날짜를 올바른 ISO 형식으로 변환하기 위해 다른 줄을 추가하면됩니다.
const max = dates.reduce (function (a, b) { return math.max (a, b); }); const thateReport = 새 날짜 (max) .toisoString ();
이것들이 보고서 목록이라고 가정합니다.
- 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입니다.
우리는 가장 최근의 보고서를 알았으므로 다음에 내용을 추출해야합니다. 최근 보고서 변수 아래에 최근 보고서라는 새 변수를 작성하고 빈 함수를 할당하십시오.
이 기능이 수동으로 호출하는 대신 항상 실행해야한다는 것을 알고 있듯이 JavaScript Parser가 도달 할 때 자체적으로 실행되는 IFFE (즉시 기능 표현식)로 전환하는 것이 합리적입니다. 이것은 추가 괄호로 의미됩니다.
const thateReportContents = (() => { }) ();
이 기능에서는 기본 FS 모듈의 readFilesync () 메소드를 사용하여 가장 최근 보고서의 내용을 반환 할 수 있습니다. 이것은 JSON 형식이므로 일반 JavaScript 객체로 구문 분석하는 것이 중요합니다.
const thateReportContents = (() => { const output = fs.readfilesync ( Dirname "/"최근 report.replace (/:/g, "_") ".json", "UTF8", (err, results) => { 반환 결과; } ); return JSON.PARSE (출력); }) ();
그런 다음 CompareReports () 함수를 호출하고 현재 보고서와 최신 보고서를 모두 인수로 전달하는 문제입니다.
CompareReports (최근 ReportContents, results.js);
현재 이것은 몇 가지 세부 정보를 콘솔에 인쇄하여 보고서 데이터를 테스트 할 수 있습니다.
https://www.lukeharrison.dev/ 2020-02-01T00 : 25 : 06.918Z https://www.lukeharrison.dev/ 2020-02-01T00 : 25 : 42.169Z
이 시점에서 오류가 발생하는 경우 튜토리얼의 이전부터 유효한 콘텐츠없이 report.json 파일 또는 보고서를 삭제하십시오.
두 보고서를 비교하십시오
나머지 주요 요구 사항은 두 웹 사이트의 두 보고서를 비교할 수있는 기능이었습니다. 이를 구현하는 가장 쉬운 방법은 사용자가 전체 보고서 파일 경로를 명령 줄 인수로 전달하여 CompareERPORTS () 함수로 보내는 것입니다.
명령 줄에서 이것은 다음과 같습니다.
노드 lh.js-from lukeharrison.dev/2020-02-01T00:25:06.918Z--cnn.com/2019-12-16T15:127.169Z
이를 달성하려면 URL 명령 줄 인수의 존재를 확인하는 조건부 IF 문을 편집해야합니다. 사용자가 방금 경로를 통과했는지 확인하기 위해 추가 점검을 추가합니다. 그렇지 않으면 이전과 같이 URL을 확인하십시오. 이렇게하면 새로운 등대 감사를 방지 할 것입니다.
if (argv.from && argv.to) { } else if (argv.url) { // et al }
이 JSON 파일의 내용을 추출하여 JavaScript 객체로 구문 분석 한 다음 CompareReports () 함수로 전달해 봅시다.
우리는 가장 최근의 보고서를 검색하기 전에 이미 JSON을 구문 분석했습니다. 이 기능을 자체 도우미 기능으로 외삽하여 두 위치에서 사용할 수 있습니다.
최신 ReportContents () 함수를 기본으로 사용하여 파일 경로를 인수로 받아들이는 getContents ()라는 새 함수를 만듭니다. JavaScript Parser가 찾는 즉시 실행을 원하지 않기 때문에 IFFE가 아닌 일반 기능이라는 것이 IFFE가 아닌 정기적 인 기능인지 확인하십시오.
const getContents = pathstr => { const output = fs.readfilesync (pathstr, "utf8", (err, results) => { 반환 결과; }); return JSON.PARSE (출력); }; const compraleReports = (from, to) => { Console.log ([ "FinalUrl"] "" "에서 ["FetchTime "]); console.log ([ "finalUrl"] ""to [ "fetchTime"]); };
그런 다음 최근 retrapolated helper 함수를 사용하려면 최근 reportContents () 함수를 업데이트하십시오.
const thateReportContents = getContents (dirname '/'최근 report.replace (/:/g, '_') '.json');
새로운 조건부로 돌아가서 비교 보고서의 내용을 CompareReports () 함수에 전달해야합니다.
if (argv.from && argv.to) { 비교 포트 ( getContents (Argv.from ".json"), getContents (Argv.to ".json") ); }
이전과 마찬가지로, 이것은 콘솔의 보고서에 대한 몇 가지 기본 정보를 인쇄하여 모든 것이 잘 작동한다는 것을 알려 주어야합니다.
노드 lh.js-from lukeharrison.dev/2020-01-31t23_24_41.786z-to lukeharrison.dev/2020-02-01t11_16_251z
다음으로 이어질 것입니다.
https://www.lukeharrison.dev/ 2020-01-31T23_24_41.786Z https://www.lukeharrison.dev/ 2020-02-01t11_16_25.221Z
비교 논리
이 개발 부분에는 비교 논리를 구축하여 CompareReports () 함수에서받은 두 보고서를 비교하는 것이 포함됩니다.
Lighthouse가 반환하는 객체 내에는 다른 개체 목록 성능 지표, 기회 및 정보가 포함 된 감사라는 속성이 있습니다. 여기에는 많은 정보가 있으며,이 도구의 목적에 관심이없는 많은 정보가 있습니다.
다음은 우리가 비교하려는 9 가지 성능 메트릭 중 하나 인 First Contentful Paint의 항목입니다.
"일주일이 많은 페인트": { "ID": "최초의 경감", "제목": "최초의 콘텐츠 페인트", "설명": "첫 번째 콘텐츠 페인트는 첫 번째 텍스트 나 이미지가 페인트되는 시간을 나타냅니다. [자세히 알아보기] (https://web.dev/first-contentful-paint)." "점수": 1, "ScoredIsplayMode": "숫자", "NumericValue": 1081.661, "displayValue": "1.1 s" }
이 9 가지 성능 메트릭의 키를 나열하는 배열을 만듭니다. 이를 사용하여 감사 오브젝트를 필터링 할 수 있습니다.
const compraleReports = (from, to) => { const metricfilter = [ "일주일이 많은 페인트", "첫 번째 주인", "Speed-Index", "예상 입력 --- 변호사", "총 블로킹 타임", "Max-Potential-Fid", "최신 시간-바이트", "First-CPU-Idle", "대화식" ]; };
그런 다음 보고서의 감사 객체 중 하나를 살펴본 다음 필터 목록에 대한 이름을 상호 참조합니다. (둘 다 동일한 컨텐츠 구조를 가지고 있으므로 어떤 감사 객체가 중요하지 않습니다.)
거기에 있으면 훌륭합니다. 우리는 그것을 사용하고 싶습니다.
const metricfilter = [ "일주일이 많은 페인트", "첫 번째 주인", "Speed-Index", "예상 입력 --- 변호사", "총 블로킹 타임", "Max-Potential-Fid", "최신 시간-바이트", "First-CPU-Idle", "대화식" ]; for ([ "Audits"]에서 auditobj를 입력하자) { if (metricfilter.includes (AuditoBj)) { Console.log (AuditoBJ); } }
이 console.log ()는 아래 키를 콘솔에 인쇄합니다.
최초의 경감 최초의 부인 스피드 인덱스 예상 입력-변호 총 블로킹 시간 최대 수정 첫 번째 바이트 First-CPU-Idle 대화식
즉, [ 'Audits'] [AuditoBj] .numericValue 및 [ 'Audits'] [AuditoBj] .numericValue에서 각각 메트릭 자체에 액세스하기 위해 사용한다는 것을 의미합니다.
키로 콘솔에 이들을 인쇄한다면 다음과 같은 출력이 발생합니다.
최초의 컨텐츠 1081.661 890.774 최초의 부인 1081.661 954.774 속도-인덱스 15576.70313351777 1098.62294504341 예상 입력-변호사 12.8 12.8 총 차단 시간 59 31.5 MAX-POTENTION-FID 153 102 최신 시간 16.85999999999985 16.096000000000004 First-CPU-IDLE 1704.8490000000002 1918.774 대화식 2266.2835 2374.3615
우리는 지금 필요한 모든 데이터를 가지고 있습니다. 이 두 값의 백분율 차이를 계산 한 다음 앞에서 설명한 색상 코드 형식을 사용하여 콘솔에 로그인하면됩니다.
두 값 사이의 백분율 변화를 계산하는 방법을 알고 있습니까? 나도. 고맙게도 모두가 가장 좋아하는 모 놀리 식 검색 엔진이 구조에 왔습니다.
공식은 다음과 같습니다.
((에서) / From) x 100
따라서 첫 번째 보고서에 대한 속도 지수가 5.7s 인 다음 두 번째 (To)의 경우 2.1s 값을 가지고 있다고 가정 해 봅시다. 계산은 다음과 같습니다.
5.7-2.1 = 3.6 3.6 / 5.7 = 0.63157895 0.63157895 * 100 = 63.157895
소수점 이하 두 자리로 반올림하면 63.16%의 속도 지수가 감소합니다.
이것을 Metricfilter 배열 아래의 CompareERPORTS () 함수 내부의 도우미 기능에 넣으십시오.
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", "interactive" ]; 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)를 던지면; } ); }); } 또 다른 { 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).
행운을 빌어요!
위 내용은 Google Lighthouse 보고서를 기록하고 비교하기위한 Node.js 도구 구축의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

라이브 토크 나 수업 중에 대화식 애니메이션을 표시해야한다면 슬라이드와 상호 작용하기가 항상 쉽지 않다는 것을 알 수 있습니다.

Astro를 사용하면 빌드 중에 대부분의 사이트를 생성 할 수 있지만 Fuse.js와 같은 것을 사용하여 검색 기능을 처리 할 수있는 작은 서버 측 코드가 있습니다. 이 데모에서는 퓨즈를 사용하여 개인 "북마크"세트를 검색합니다.

문서가 저장되는 동안 Google 문서에서 볼 수있는 것과 유사한 프로젝트 중 하나에서 알림 메시지를 구현하고 싶었습니다. 다시 말해, a

몇 달 전에 나는 해커 뉴스를 썼고 (하나와 마찬가지로) IF 문을 사용하지 않는 것에 대한 (현재 삭제 된) 기사를 가로 질러 달렸습니다. 이 아이디어를 처음 접한다면 (나처럼

공상 과학 소설의 초기부터 우리는 우리와 대화하는 기계에 대해 환상을 가지고 있습니다. 오늘은 평범합니다. 그럼에도 불구하고 제작 기술

Gutenberg가 핵심으로 풀려 났을 때를 기억합니다. 왜냐하면 나는 그날 WordCamp에 있었기 때문입니다. 지금은 몇 달이 지났으므로 점점 더 많은 것을 상상합니다.

대부분의 웹 애플리케이션의 배후에있는 아이디어는 데이터베이스에서 데이터를 가져 와서 최상의 방법으로 사용자에게 제시하는 것입니다. 우리가 거기에서 데이터를 다룰 때

#039;는 당신이 의미있는 것처럼 보일 수있는 상황에 대한 약간의 단계를 수행하자. 이것에서


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

Atom Editor Mac 버전 다운로드
가장 인기 있는 오픈 소스 편집기

Dreamweaver Mac版
시각적 웹 개발 도구

PhpStorm 맥 버전
최신(2018.2.1) 전문 PHP 통합 개발 도구

mPDF
mPDF는 UTF-8로 인코딩된 HTML에서 PDF 파일을 생성할 수 있는 PHP 라이브러리입니다. 원저자인 Ian Back은 자신의 웹 사이트에서 "즉시" PDF 파일을 출력하고 다양한 언어를 처리하기 위해 mPDF를 작성했습니다. HTML2FPDF와 같은 원본 스크립트보다 유니코드 글꼴을 사용할 때 속도가 느리고 더 큰 파일을 생성하지만 CSS 스타일 등을 지원하고 많은 개선 사항이 있습니다. RTL(아랍어, 히브리어), CJK(중국어, 일본어, 한국어)를 포함한 거의 모든 언어를 지원합니다. 중첩된 블록 수준 요소(예: P, DIV)를 지원합니다.

에디트플러스 중국어 크랙 버전
작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음
