Shiv ENOW large front end

Company official website: CVTE(Guangzhou Shiyuan Stock)

Team: ENOW team of CVTE software Platform Center for Future Education

The author:

Hello, everyone. I’m Koba. An ordinary, and unwilling to ordinary front-end development engineer!

You’re familiar with running points, right? Especially the rice fan, the boss of thunder that disobey? Then run a point! I think it’s fresh in my mind, right? Ha, ha, ha

Are you familiar with performance tuning in your daily front-end development? But how do you usually determine if performance is improving? Hence Google’s open source tool, Lighthouse.

Lighthouse is designed to analyze web applications and web pages, gathering modern performance metrics and providing insights into developer best practices. For front-end developers, it is easy to see the deficiencies in the project and how to optimize them. It is a rare artifact in daily development!

Simple use

Lighthouse Plug-in Installation

In the Chrome store, search for Lighthouse and add it.

Set test items

Then open the plug-in in the Plug-in bar at the top of Chrome. By clicking on the Settings icon, you can also choose which items to test (run scores) and whether to test PC or mobile web pages.

Test (Run score)

Then click on the Generate Report button to go straight to the test and the results will come out after a while. The graph below is our ENOW big front end team nuggets homepage test score, can see nuggets SEO optimization is still very good, hahaha ~

The whole test report identifies various performance related parameters in the page, and then gives us a lot of relevant optimization suggestions. If you are interested, you can go into depth to understand each parameter oh ~

Now the performance testing tool is there, but there is no detection of this can only be a page to test, good trouble ah. If there are dozens of pages you have to click one by one. Would you go to the trouble? Added: ak47 schematic item and loot added for people like Koha who are tired of repetitive work

Now the question is, is there a convenient way? It’s not the way to test them one by one.

Don’t worry, the dry goods will be here soon

In addition to using the Chrome plugin, you can also call Lighthouse from the command line.

1. Install lighthouse globally

npm install -g lighthouse
Copy the code

2. Enter your page

lighthouse http://test.com
Copy the code

Koha will not show here, let’s go straight to the theme, hey hey ~

Make running gear

We’re going to build the front-end performance runner with the help of lighthouse’s NPM package and gulp scripts.

1. Initialize the project

Create a new folder, Enow-Lighthouse in this case, create package.json and write the relevant content, and then CNPM install some dependency packages that we need to write the tool

{
  "name": "enow-lighthouse"."version": "1.0.0"."description": "ENOW Front End -- Lighthouse Testing Tools"."main": "index.js"."scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"."start":"gulp start"
  },
  "author": ""."license": "ISC"."devDependencies": {
    "chrome-launcher": "^ 0.13.4"."del": "^ 6.0.0"."fs-extra": "^ 9.1.0"."gulp": "^ 4.0.2." "."lighthouse": "^ 7.3.0"}}Copy the code

2. Write gulp scripts

1. Create gulpfile.js in the root directory

To test if our project works, write the following code in gulpfile.js. If normal, the ENOW large front end ~ shown below will be displayed

const gulp = require("gulp")
const lighthouse = require('lighthouse');
const chromeLauncher = require('chrome-launcher');
const printer = require('lighthouse/lighthouse-cli/printer');
const Reporter = require('lighthouse/lighthouse-core/report/report-generator');
const fs = require('fs-extra');
const del = require("del")
let chrome

gulp.task("start".async function(cb){
  console.log("ENOW Big front-end")
  cb()
})
Copy the code

2. Added the launchChrome method, which is used to launchChrome and return the required chrome information

  • --headlessDo not openbrowserwindow
  • --disable-gpuIndicates disabled.gpu
  • --no-sandboxIndicates that the sandbox mode is disabled
/ / open chrome
async function launchChrome() {
  try {
      chrome = await chromeLauncher.launch({
          chromeFlags: [
              "--disable-gpu"."--no-sandbox"."--headless"].enableExtensions: true.logLevel: "error"
      });
      return {
          port: chrome.port,
          chromeFlags: [
              "--headless"].logLevel: "error"}}catch (e) {
      console.log("ENOW lighthouse error: launching Chrome ", e); }}Copy the code

3. Added the Lighthouse Runner method, which runs lighthouse tests and returns the results

// Start the Lighthouse test
async function lighthouseRunner(url, opt, config={extends: 'lighthouse:default'}) {
  try {
      return await lighthouse(url, opt, config);
  } catch (e) {
      console.log("ENOW lighthouse error: running lighthouse"); }}Copy the code

4. Added the genReport method, which is used to get the HTML page of the current page report and return the generated HTML page

// Generate a report for the current page
function genReport(result) {
  return Reporter.generateReport(result.lhr, 'html');
}
Copy the code

5. Add the run method, which is the test entry for each page

// Test entry for each page
async function run(url, timestamp, config) {
  let chromeOpt = await launchChrome();
  let result = await lighthouseRunner(url, chromeOpt, config);
  let report = genReport(result);
  // Save the report
  await printer.write(report, 'html'.`./cases/lighthouse-report@${timestamp}.html`);
  / / close the chrome
  await chrome.kill();
  return
}
Copy the code

6. Modify gulp. Task, create the Cases folder in the root directory, run NPM run start, wait a while, and you will find the performance test report generated in the newly created cases folder

gulp.task("start".async function(cb){
  let taskList = [
    `https://juejin.cn/`.`https://juejin.cn/`.`https://juejin.cn/`,]for(let item of taskList){
    let timestamp = Date.now();
    await run(item,timestamp)
  }
  cb()
})
Copy the code

Small feather, you write a lot of things in here, za looked at the skull all ache!!

There’s a lot going on here, but the logic is easy to follow

Wait for Koba to analyze a wave of friends:

  • First we runnpm run startIs calledgulp startAnd then you entergulp.task()In the
  • thengulp.task()Is the traversaltaskListAnd then callRun method(Test entry for each page)
  • Run methodcalllaunchChrome()And then returnchromeThe relevant information
  • Run methodcalllighthouseRunner()And return the test results
  • Run methodcallgenReport()Returns the generatedhtmlpage
  • Run methodthehtmlPages are written to a file
  • Shut downchrome

So far, the code in gulpfile.js is as follows

/* * @description: * @author: Koba * @Date: 2021-04-11 23:05:22 * @LasteditTime: 2021-04-12 00:30:55 */
const gulp = require("gulp")
const lighthouse = require('lighthouse');
const chromeLauncher = require('chrome-launcher');
const printer = require('lighthouse/lighthouse-cli/printer');
const Reporter = require('lighthouse/lighthouse-core/report/report-generator');
const fs = require('fs-extra');
const del = require("del")
let chrome

/ / open chrome
async function launchChrome() {
  try {
      chrome = await chromeLauncher.launch({
          chromeFlags: [
              "--disable-gpu"."--no-sandbox"."--headless"].enableExtensions: true.logLevel: "error"
      });
      return {
          port: chrome.port,
          chromeFlags: [
              "--headless"].logLevel: "error"}}catch (e) {
      console.log("ENOW lighthouse error: launching Chrome ", e); }}// Start the Lighthouse test
async function lighthouseRunner(url, opt, config={extends: 'lighthouse:default'}) {
  try {
      return await lighthouse(url, opt, config);
  } catch (e) {
      console.log("ENOW lighthouse error: running lighthouse"); }}// Get a report for the current page
function genReport(result) {
  return Reporter.generateReport(result.lhr, 'html');
}

// Test entry for each page
async function run(url, timestamp, config) {
  let chromeOpt = await launchChrome();
  let result = await lighthouseRunner(url, chromeOpt, config);
  let report = genReport(result);
  // Save the report
  await printer.write(report, 'html'.`./cases/lighthouse-report@${timestamp}.html`);
  / / close the chrome
  await chrome.kill();
  return
}

gulp.task("start".async function(cb){
  let taskList = [
    `https://juejin.cn/`.`https://juejin.cn/`.`https://juejin.cn/`,]for(let item of taskList){
    let timestamp = Date.now();
    await run(item,timestamp)
  }
  cb()
})
Copy the code

3. Remove the task list

In general, our task list is not written directly into the method. In order to fit the idea of low-coupling, high-cohesion programming, we separate our task list and import it into gulpfile.js using require. Create tasklist.js in the root directory.

When we need to measure the performance of a particular page, we can simply change taskList.js to the same URL. If you want to measure the overall performance of your site, just copy all of your urls into it.

For an average score and a complete report, please proceed to the next section (✧◡✧)

// taskList.js
module.exports = [
  `https://juejin.cn/`.`https://juejin.cn/`.`https://juejin.cn/`,]Copy the code
// gulpfile.js
const taskList = require("./taskList")

// omit the middle code...

gulp.task("start".async function(cb){
  for(let item of taskList){
    let timestamp = Date.now();
    await run(item,timestamp)
  }
  cb()
})
Copy the code

4. Generate a general report

Although our current project can also run points with one key, have you found that there are many generated files, and you have to click in one by one to see our page information, is that ok?

Stop, don’t ask, ask is a concubine can not do!!

Ha ha ha, tease you, under the programmer in addition to product manager need not be completed, other time is super severe drop formation [manual]

If I change the code,

NPM run start Starts the running program of lighthouse and prints out the results of the lighthouse run to see what happens first.

A file.txt file will be generated in our root directory. On opening it… What the hell is this? It’s totally unwatchable. What can we do about it?

Don’t worry. The mountain people have a plan

Open up our original generated report and do a little analysis. In file.txt, the output data in the LHR field is actually the output data in our console. Then look at the data in the console.

Add a write() method to output to a file. Here is our general report

// Generate a total report
async function write(file, report) {
  try {
      await fs.outputFile(file, report);
      return true
  } catch (e) {
      console.log("error while writing report ", e); }}Copy the code

Run (); run (); run (); run ()

async function run(url, timestamp, num, config) {
  let chromeOpt = await launchChrome();
  let result = await lighthouseRunner(url, chromeOpt, config);
  let report = genReport(result);
  // Save the report
  await printer.write(report, 'html'.`./cases/lighthouse-report@${timestamp}-${num}.html`);
  result.lhr.audits['first-contentful-paint'].rawValue;
  let res = {
      audits: {"first-contentful-paint":result.lhr.audits['first-contentful-paint']},categories:result.lhr.categories,
      lighthouseVersion:result.lhr.lighthouseVersion,
      requestedUrl:result.lhr.requestedUrl
  }
  / / close the chrome
  await chrome.kill();
  return res;//result.lhr
}
Copy the code

New summary/template/root directory template. The HTML, the template. The HTML is our general report template file, kohane is literally write here, friends are free to play ~

Modify the gulp. Task ()

gulp.task("start".async function(cb){
  let timestamp = Date.now();
  let spent = [];
  console.log(` altogether${taskList.length}A task `)
  for (let i = 0; i < taskList.length; i++) {
    console.log(Current first `${i+1}A task `)
    spent.push(await run(taskList[i], timestamp, i));
  }
  // Replace the contents of the template
  let template = await fs.readFileSync('./summary/template/template.html'.'utf-8');
  let summary = Reporter.replaceStrings(template, [{
    search: '%%TIME_SPENT%%'.replacement: JSON.stringify(spent)
  }, {
    search: '%%TIMESTAMP%%'.replacement: timestamp
  }]);
  await write(`./summary/report/summary@${timestamp}.html`, summary)
  cb()
})
Copy the code

Hey, hey, hey, hey, hey, hey, hey, hey, hey, hey, hey, hey, hey.

After NPM run start, we will find a new HTML file generated in our summary/report. Let’s open it

5. Add commands on the PC and mobile devices

Emmm, no, there is a problem, because we are always testing mobile, how can we test PC?? You can’t change the configuration every time you test it, can you?

Constants. Js, Lighthouse -desktop-config.js (PC), lighthouse-mobile-config.js (mobile) added in root directory

Gulp.task () is not enough, so let’s add another one. Then I’ll change the name to create:report-desktop and create:report-mobile. Modify gulpfile.js, package.json.

// gulpfile.js
const desktopConfig = require('./lighthouse-desktop-config.js');
const mobileConfig = require('./lighthouse-mobile-config.js');


// omit some code...

gulp.task('create:report-desktop'.async function(cb){
  let timestamp = Date.now();
  let spent = [];
  console.log(` altogether${taskList.length}A task `)
  for (let i = 0; i < taskList.length; i++) {
    console.log(Current first `${i+1}A task `)
    spent.push(await run(taskList[i], timestamp, i , desktopConfig));
  }
  // Replace the contents of the template
  let template = await fs.readFileSync('./summary/template/template.html'.'utf-8');
  let summary = Reporter.replaceStrings(template, [{
    search: '%%TIME_SPENT%%'.replacement: JSON.stringify(spent)
  }, {
    search: '%%TIMESTAMP%%'.replacement: timestamp
  }]);
  await write(`./summary/report/summary@${timestamp}.html`, summary)
  cb()
})

gulp.task('create:report-mobile'.async function(cb){
  let timestamp = Date.now();
  let spent = [];
  console.log(` altogether${taskList.length}A task `)
  for (let i = 0; i < taskList.length; i++) {
    console.log(Current first `${i+1}A task `)
    spent.push(await run(taskList[i], timestamp, i, mobileConfig));
  }
  // Replace the contents of the template
  let template = await fs.readFileSync('./summary/template/template.html'.'utf-8');
  let summary = Reporter.replaceStrings(template, [{
    search: '%%TIME_SPENT%%'.replacement: JSON.stringify(spent)
  }, {
    search: '%%TIMESTAMP%%'.replacement: timestamp
  }]);
  await write(`./summary/report/summary@${timestamp}.html`, summary)
  cb()
})
Copy the code
// package.json

{
  "name": "enow-lighthouse"."version": "1.0.0"."description": "ENOW Front End -- Lighthouse Testing Tools"."main": "index.js"."scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"."create:report-desktop":"gulp create:report-desktop"."create:report-mobile":"gulp create:report-desktop"
  },
  "author": ""."license": "ISC"."devDependencies": {
    "chrome-launcher": "^ 0.13.4"."del": "^ 6.0.0"."fs-extra": "^ 9.1.0"."gulp": "^ 4.0.2." "."lighthouse": "^ 7.3.0"}}Copy the code

At this point, we no longer have the start command, so the start commands become NPM run create:report-desktop and NPM run create:report-mobile

6. Delete the old test file

But have you noticed that our report files pile up every time we run?

Three new gulp.task() files are added to gulpfile.js. Then modify the commands in package.json

  • npm run mobile: Clean up the file, and then perform a mobile run
  • npm run desktop: Clean up the files and run PC runs
  • npm run clean: Clean files
  • npm run create:report-mobile: Performs mobile runs
  • npm run create:report-desktop: Runs points on the PC

In gulp, gulp.series() is executed sequentially, one at a time. Gulp.paralle (), on the other hand, runs concurrently.

// gulpfile.js
// Clear data
gulp.task('clean:report'.function (cb) {
  del([
      'cases/**/*'.'summary/report/**/*',
  ], cb);
  cb()
});

// gulp.series: execute in sequence
// gulp. Paralle: can perform parallel computation
gulp.task("start-desktop", gulp.series("clean:report"."create:report-desktop"), function () {})
gulp.task("start-mobile", gulp.series("clean:report"."create:report-mobile"), function () {})
Copy the code
// package.json
{
  "name": "enow-lighthouse"."version": "1.0.0"."description": "ENOW Front End -- Lighthouse Testing Tools"."main": "index.js"."scripts": {
    "mobile":"gulp start-mobile"."desktop":"gulp start-desktop"."clean":"gulp clean:report"."create:report-desktop":"gulp create:report-desktop"."create:report-mobile":"gulp create:report-desktop"
  },
  "author": ""."license": "ISC"."devDependencies": {
    "chrome-launcher": "^ 0.13.4"."del": "^ 6.0.0"."fs-extra": "^ 9.1.0"."gulp": "^ 4.0.2." "."lighthouse": "^ 7.3.0"}}Copy the code

Ok, now we have the whole running gear. If a guy tells you how awesome his web page is, don’t hesitate to take out this running tool and fight it out

After the language

This paper mainly combines Google’s open source project Lighthouse and gulp script to write a front-end performance running tool. It is mainly used to help front-end development engineers to have a more comprehensive understanding of their website/project, quickly identify the advantages and disadvantages, as well as the direction of improvement.