欧美三级国产三级日韩三级_亚洲熟妇丰满大屁股熟妇_欧美亚洲成人一区二区三区_国产精品久久久久久模特

Lighthouse 在小程序中的實(shí)踐 - 新聞資訊 - 云南小程序開發(fā)|云南軟件開發(fā)|云南網(wǎng)站建設(shè)-昆明葵宇信息科技有限公司

159-8711-8523

云南網(wǎng)建設(shè)/小程序開發(fā)/軟件開發(fā)

知識

不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價(jià)值,我們在追求其視覺表現(xiàn)的同時(shí),更側(cè)重于功能的便捷,營銷的便利,運(yùn)營的高效,讓網(wǎng)站成為營銷工具,讓軟件能切實(shí)提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序?yàn)楹笃谏壧峁┍憬莸闹С郑?

您當(dāng)前位置>首頁 » 新聞資訊 » 小程序相關(guān) >

Lighthouse 在小程序中的實(shí)踐

發(fā)表時(shí)間:2021-4-22

發(fā)布人:葵宇科技

瀏覽次數(shù):70

前言

目前哈啰前端應(yīng)用質(zhì)量監(jiān)控使用到了 Lighthouse 作為首頁性能問題定性檢查的工具,在使用過程中,我們基于 Lighthouse Plugin 對其原有能力進(jìn)行擴(kuò)展,用于檢測 web 端和小程序的性能問題,在實(shí)踐中也積累了些經(jīng)驗(yàn),希望能通過本文的分享,給大家一些幫助。

Lighthouse 簡介

Lighthouse 是一個(gè)開源的自動化檢測工具,通過內(nèi)置審計(jì)模塊,分析 web 應(yīng)用和 web 頁面的性能指標(biāo),最終給出頁面的首屏得分和最佳實(shí)踐指南。

使用方式

使用方式有四種,具體可以參考官方使用說明(github.com/GoogleChrom…) ,啟動姿勢很重要,大家選一款適合自己的。

模塊實(shí)現(xiàn)

整體架構(gòu)圖如上,模塊的實(shí)現(xiàn)細(xì)節(jié)可以參考 Lighthouse 模塊實(shí)現(xiàn)。 Lighthouse Plugin 主要會涉及到 Gatherers、Audits、Categories 這三個(gè)模塊。

檢測報(bào)告

Lighthouse 的檢測報(bào)告默認(rèn)展示 5 類信息:

  • Performance(性能)
  • Progressive Web App(漸進(jìn)式 web 應(yīng)用)
  • Accessibility(無障礙)
  • Best Practices(最佳實(shí)踐)
  • SEO(SEO)

可以通過調(diào)用不同 config 來展示其中幾類。

Lighthouse Plugin 開發(fā)入門

可以參考官方文檔 ,這里給出一個(gè)簡單的示例。開發(fā)一個(gè)plugin,主要分為以下兩步:

一、新建 Lighthouse Plugin項(xiàng)目 創(chuàng)建一個(gè) npm 包,包含 plugin.js 和 package.json:

module.exports = {
  // 這里可以新增自己的 audit(審計(jì)項(xiàng))
  audits: [{path: 'lighthouse-plugin-example/test-audit.js'}],
  // 這里可以設(shè)置自定義分類的一些信息,比如標(biāo)題、描述、引用的審計(jì)項(xiàng)等
  category: {
    title: 'title',
    description: 'description',
    auditRefs: [{id: 'test-id', weight: 1}],
  },
};
package.json

{
  "name": "lighthouse-plugin-example",
  "main": "plugin.js",
  "peerDependencies": {
    "lighthouse": "^5.6.0"
  },
  "devDependencies": {
    "lighthouse": "^5.6.0"
  }
}
復(fù)制代碼

注:Lighthouse 要按 peerDependencies 方式引入,避免重復(fù)下載。

由于上例用到了新的審計(jì)項(xiàng),所以我們也需要新建這個(gè)文件

const { Audit } = require('lighthouse');
class TestAudit extends Audit {
  static get meta() {
    return {
      // 這里定義審計(jì)項(xiàng)的一些配置,比如標(biāo)題、異常描述、依賴的artifacts等
      requiredArtifacts: ['devtoolsLogs'],
    };
  }
  static audit(artifacts) {
    // lighthouse 運(yùn)行過程會經(jīng)過一系列的采集器(gatherers),
    // 每個(gè)采集器都會收集自己的目標(biāo)信息,并生成中間產(chǎn)物(artifacts)
    return {
      score: 1,
    };
  }
}
module.exports = TestAudit;
復(fù)制代碼

二、使用Lighthouse Plugin

如果是命令行,直接運(yùn)行:

復(fù)制代碼

如果是 npm 方式運(yùn)行, Lighthouse 的配置需改為:

  extends: 'lighthouse:default',
  plugins: ['lighthouse-plugin-example'],
  settings: {
    // ...
  },
};
復(fù)制代碼

Lighthouse Plugin 在項(xiàng)目中的實(shí)踐

先聊一聊為什么要做 哈啰前端應(yīng)用質(zhì)量監(jiān)控的規(guī)劃之一,就是統(tǒng)一使用Lighthouse 做多端的首屏性能的定性檢查。瀏覽器端是天然支持的,難點(diǎn)是小程序,無法直接在瀏覽器中直接運(yùn)行,也就無法使用 Lighthouse 進(jìn)行定性檢查。所幸,現(xiàn)在有 taro、antmove 等一眾的開源工具,可以借助這些工具將小程序轉(zhuǎn)換為運(yùn)行在瀏覽器端的應(yīng)用,如此一來,我們可以將 Lighthouse 集成到我們的工程體系中來,使用相同的工具鏈對瀏覽器端和小程序端進(jìn)行定性檢查。

不憑空的制造需求,是商業(yè)公司技術(shù)團(tuán)隊(duì)的立足之本。在整體目標(biāo)的引導(dǎo)下,我們要考慮如何來檢查小程序的性能,傳統(tǒng)意義上的Web頁面的檢查方式是否可以直接搬過來呢?答案是否定的,而對于小程序的技術(shù)實(shí)現(xiàn)原理,Lighthouse默認(rèn)那一套不能直接照搬。運(yùn)行在瀏覽器端的小程序,F(xiàn)MP、FCI、TTI等都可以做橫向?qū)Ρ?,但其結(jié)果的可靠性還要進(jìn)行推敲,除此之外,我們需要有一套符合小程序技術(shù)特性的分析方法和工具,我們需要開發(fā)對應(yīng)的Lighthouse Plugin,對應(yīng)的Gatherers、Audits和Categories。

這張截圖來自支付寶小程序的部分檢測項(xiàng),在傳統(tǒng) web 端檢測的基礎(chǔ)上,多了許多小程序特有檢測(比如 setData 頻率、數(shù)據(jù)量、API 調(diào)用次數(shù)、同/異步調(diào)用等),這些指標(biāo)目前 Lighthouse 并非天生就覆蓋到。

為小程序定制一個(gè)插件

以下以編寫一個(gè)審計(jì)支付寶小程序Native API調(diào)用次數(shù)的插件為例,簡單的總結(jié)如下:

業(yè)務(wù)代碼注入采集邏輯 + gatherer 收集采集數(shù)據(jù) + audit 消費(fèi)數(shù)據(jù)并計(jì)算結(jié)果

業(yè)務(wù)代碼注入采集邏輯

定義一個(gè)日志采集對象window.nativeCall,通過調(diào)用window.nativeCall ,通過調(diào)用 window.nativeCall.push 采集一次調(diào)用行為,示例代碼如下。

window.$$nativeCall = {
    calls: [],
  push: function (type, callInfo) {
    this.calls.push({ timestamp: Date.now(), type, callInfo });
  },
};
function $$myproxy(my) {
  return new Proxy(my, {
    get(target, key) {
      const keyValue = https://www.wxapp-union.com/target[key];
      // 如果是API方法,則代理原方法
      if (typeof keyValue ==='function') {
        return $$myProxyFn(keyValue, target, key);
      }
      // 否則,直接上報(bào)了一個(gè)API屬性的調(diào)用檢測點(diǎn)
            window.$$nativeCall.push('api-attr-called', JSON.stringify({
        key: `my.${key}`,
      }));
      return keyValue;
    }
  });
};
function $$myProxyFn(fn, that, key) {
  return (function (...args) {
    // 上報(bào)了一個(gè)AP方法的調(diào)用檢測點(diǎn),攜帶自定義參數(shù)
    window.$$nativeCall.push('api-method-called', JSON.stringify({
      key: `my.${key}`,
      args,
    }));
    try {
      const result = fn.apply(this, args);
      // 上報(bào)了一個(gè)AP方法的成功調(diào)用的檢測點(diǎn),叫 api-method-success-called
      window.$$nativeCall.push('api-method-success-called', JSON.stringify({
        key: `my.${key}`,
        args,
                result: err,
      }));
    } catch (err) {
      // 上報(bào)了一個(gè)AP方法的異常調(diào)用檢測點(diǎn),叫 api-method-error-called
      window.$$nativeCall.push('api-method-error-called', JSON.stringify({
        key: `my.${key}`,
        args,
                result: err,
      }));
    }
  }).bind(that);
}
復(fù)制代碼

示例代碼寫的比較簡單,只是將調(diào)用信息存儲在了window.$$nativeCall中。這段代碼需要通過編譯工具鏈來插入到小程序的業(yè)務(wù)代碼中,以攔截小程序代碼中所有的Native API的調(diào)用。

自定義 audit 審計(jì)模塊

在進(jìn)行審計(jì)分析之前,我們需要一個(gè) Gatherer 來獲取window.$$nativeCall采集到的信息。

const { Gatherer } = require('lighthouse');
class CustomNativeCall extends Gatherer {
  public async afterPass(passContext) {
    const { driver } = passContext;
    const $$nativeCall = await driver.evaluateAsync('window.$$nativeCall');
    if ($$nativeCall) {
      return $$nativeCall.calls;
    }
    return [];
  }
}
module.exports = CustomNativeCall;
復(fù)制代碼

收集器寫好了。我們需要編寫 Audit 的處理邏輯,這里,我們以統(tǒng)計(jì) Native API 調(diào)用次數(shù)(api-method-called)為例:

const { Audit } = require('lighthouse');
class ApiMethodCalledAudit extends Audit {
  static get meta() {
    return {
     // 定義好 id,這樣 plugin.js 就能找到這個(gè)審計(jì)項(xiàng)
     id: 'api-method',
     // 這里引入上面定義好的收集器
     requiredArtifacts: ['CustomNativeCall'],
    };
  }
  static audit(artifacts) {
    const { CustomNativeCall } = artifacts;
    const apiMap = {};
    CustomNativeCall.forEach((log) => {
     const {
       // timestamp, // 時(shí)間戳在這個(gè)審計(jì)項(xiàng)中沒用到,可以不聲明
       type,
       callInfo,
     } = log;
      // 判斷type是否是我們上報(bào)的特定類型:api-method-called
      if (type === 'api-method-called') {
        const { key } = JSON.parse(callInfo);
        // 取出api的方法名,計(jì)數(shù)
        apiMap[key] = apiMap[key] || 0;
        apiMap[key] += 1;
      }
    });
    const result = Object.keys(apiMap).reduce((res, apiKey) => {
      res.push({
        api: apiKey,
        count: apiMap[apiKey],
      });
      return res;
    }, []);
    return {
      // 生成表格明細(xì)
      details: Audit.makeTableDetails(ApiMethodCalledAudit.getHeadings(), result),
      // 結(jié)果展示文案
      displayValue: `共找到 ${result.length} 次API方法調(diào)用`,
      // 評分,區(qū)間在0-1,1表示該審計(jì)項(xiàng)滿分
      score: 1,
    };
  }
  
  private static getHeadings() {
    return [
      {
        itemType: 'text',
        key: 'api',
        text: '名稱',
      },
      {
        itemType: 'numeric',
        key: 'count',
        text: '調(diào)用次數(shù)',
      },
    ];
  }
};
module.exports = ApiMethodCalledAudit;
復(fù)制代碼

最后,在我們的 plugin.js 引入 api-method-called-audit.js

module.exports = {
  audits: [{path: 'lighthouse-plugin-example/api-method-called-audit.js'}],
  category: {
    title: '容器',
    description: 'description',
    // 這里注入plugin用到的audit依賴,id取自audit里的meta.id
    auditRefs: [{id: 'api-method', weight: 1}],
  },
};
復(fù)制代碼

至此,數(shù)據(jù)上報(bào)、采集、消費(fèi)整個(gè)流程便打通了。

小程序中的實(shí)踐總結(jié) 以下整理了當(dāng)前我們實(shí)際項(xiàng)目中定義的部分日志類型、審計(jì)模塊。

日志類型

  • api-attr-called:用于 API 屬性訪問次的相關(guān)統(tǒng)計(jì)
  • api-method-error-called:用于 API 方法的異常調(diào)用次數(shù)的統(tǒng)計(jì)
  • api-method-called:用于 API 方法的調(diào)用次數(shù)情況統(tǒng)計(jì)
  • api-method-success-called:用于 API 方法的成功調(diào)用次數(shù)、耗時(shí)的統(tǒng)計(jì)
  • set-data:用于 setData 調(diào)用次數(shù)、數(shù)據(jù)大小的統(tǒng)計(jì)
  • set-data-success:用于 setData 調(diào)用耗時(shí)統(tǒng)計(jì)

Audit

  • api-async-same-args-called: 異步 API 方法相同入?yún)⒄{(diào)用
  • api-attr-called: API 屬性調(diào)用
  • api-deprecated-called: 廢棄 API 調(diào)用
  • api-duplicate-called: API 被重復(fù)調(diào)用情況(連續(xù) 20 次)
  • api-error-called: API 異常調(diào)用
  • api-long-time-called: API 調(diào)用耗時(shí)過長(超過 1000ms)
  • api-method-called: API 方法調(diào)用
  • api-sync-called: API 同步方法調(diào)用情況
  • page-node-used: 文檔節(jié)點(diǎn)復(fù)雜度
  • set-data-called: setData 調(diào)用頻繁(20 次/秒)
  • set-data-size: setData 數(shù)據(jù)量超限(超過 256kb)

Category

我們將審計(jì)項(xiàng)分為三大類:

  • performance

主要包含性能相關(guān)的審計(jì)項(xiàng),比如setData調(diào)用次數(shù)、setData單次設(shè)置的數(shù)據(jù)量、頁面節(jié)點(diǎn)數(shù)等等,這些審計(jì)項(xiàng)的優(yōu)化,可以帶來相對直觀的性能提升。

  • container

主要包含容器相關(guān)的審計(jì)項(xiàng),比如小程序api(異常、重復(fù)、耗時(shí)、相同入?yún)ⅲ┱{(diào)用、小程序native屬性調(diào)用等等,這些審計(jì)項(xiàng)和小程序運(yùn)行環(huán)境直接關(guān)聯(lián)。

  • best-practice

主要包含最佳實(shí)踐相關(guān)的審計(jì)項(xiàng),比如圖片轉(zhuǎn)webp、禁止廢棄api調(diào)用、請求異常處理、同步轉(zhuǎn)為異步api調(diào)用等等,這些審計(jì)項(xiàng)都和官方推薦的開發(fā)方式相關(guān)。

插件使用方法

以 npm 包方式為例,我們將 Lighthouse 的配置改為:

module.exports = {
  extends: 'lighthouse:default',
  plugins: [
    // 這里引入了容器檢測,性能和最佳實(shí)踐如果需要的話也可以在這里引入
    'lighthouse-plugin-miniprogram/plugins/container'
  ],
  passes: [{
    passName: 'defaultPass',
    gatherers: [
      'lighthouse-plugin-miniprogram/gatherers/custom-native-call',
    ],
  }],
  settings: {
    // ...
  },
};
復(fù)制代碼

運(yùn)行結(jié)果

這里我們用目前已經(jīng)寫好的統(tǒng)計(jì)項(xiàng)作為演示,使用方式和上例一致的。

最后

本文從實(shí)際業(yè)務(wù)出發(fā),簡要介紹了 Lighthouse在哈啰前端應(yīng)用質(zhì)量監(jiān)控中的運(yùn)用,對于如何在小程序中應(yīng)用好Lighthouse,我們目前也還在探索階段,歡迎交流。

參考資料

  • Lighthouse-developers(文章鏈接:developers.google.com/web/tools/l…
  • Lighthouse 測試內(nèi)幕(文章鏈接:juejin.im/post/5dca05…
  • Web 性能優(yōu)化地圖(文章鏈接:github.com/berwin/Blog…
  • Chrome DevTools Protocol(文章鏈接:chromedevtools.github.io/devtools-pr…
  • Lighthouse-architecture(文章鏈接:github.com/GoogleChrom…

相關(guān)案例查看更多