javascript - 在 onload 事件上加载谷歌地图仍然会在页面加载后给出加载它的灯塔消息

标签 javascript google-maps lazy-loading

我已经为我的项目运行了 chrome 审计,我被建议减少第三方代码的影响。就我而言,我正在加载谷歌地图 api。我这样做是这样的:

在我的 main.js 中,我检查要附加 map 的元素:

if (document.querySelector('.js-map')) {
  GMap.GMap('.js-map', process.env.GOOGLE_MAPS_API_KEY);
}

GMap 看起来像这样:

export function GMap(el, apiKey) {

  const gApiKey = apiKey
  const gmapApi = new GoogleMapsApi(gApiKey)
  const mapEl   = document.querySelector(el)
  const data    = {
    lat:     parseFloat(mapEl.dataset.lat ? mapEl.dataset.lat : 0),
    lng:     parseFloat(mapEl.dataset.lng ? mapEl.dataset.lng : 0),
    zoom:    parseFloat(mapEl.dataset.zoom ? mapEl.dataset.zoom: 12),
  }
  // Call map renderer
  gmapApi.load().then(() => {
    renderMap(mapEl, data);
    document.querySelector('.static-map-img').setAttribute("style", "display:none;");
    document.querySelector('.map').removeAttribute('style');
 })
}

这是 GoogleMapsApi:

 /**
 * GoogleMapsApi
 * Class to load google maps api with api key
 * and global Callback to init map after resolution of promise.
 *
 * @exports {GoogleMapsApi}
 * @example MapApi = new GoogleMapsApi();
 *          MapApi.load().then(() => {});
 */
class GoogleMapsApi {

  /**
   * Constructor
   * @property {string} apiKey
   * @property {string} callbackName
   */
  constructor(gApiKey) {

    // api key for google maps
    this.apiKey = gApiKey;

    // Set global callback
    if (!window._GoogleMapsApi) {
      this.callbackName = '_GoogleMapsApi.mapLoaded';
      window._GoogleMapsApi = this;
      window._GoogleMapsApi.mapLoaded = this.mapLoaded.bind(this);
    }
  }

  /**
   * Load
   * Create script element with google maps
   * api url, containing api key and callback for
   * map init.
   * @return {promise}
   * @this {_GoogleMapsApi}
   */
  load() {
    if (!this.promise) {
      this.promise = new Promise(resolve => {
        this.resolve = resolve;

        if (typeof window.google === 'undefined') {
          const script = document.createElement('script');
          script.src = `//maps.googleapis.com/maps/api/js?key=${this.apiKey}&callback=${this.callbackName}`;
          script.async = 'true';
          script.defer = 'true';
          script.setAttribute('rel', 'preload');
          document.body.append(script);
        } else {
          this.resolve();
        }
      });
    }

    return this.promise;
  }

  /**
   * mapLoaded
   * Global callback for loaded/resolved map instance.
   * @this {_GoogleMapsApi}
   *
   */
  mapLoaded() {

    if (this.resolve) {
      this.resolve();
    }
  }
}

export default GoogleMapsApi;

运行审核后,我已将 map 加载更改为在页面加载后发生:

window.onload = function () {
  if (document.querySelector('.js-map')) {
    GMap.GMap('.js-map', process.env.GOOGLE_MAPS_API_KEY);
  }
};

但是,我仍然从 chrome 的 lighthouse 收到相同的审核消息:

enter image description here

您可以看到一个工作示例 here .

更新

我也试过像这样用异步等待逻辑加载 map :

const loadMap = async () => {
  if (document.querySelector('.js-map')) {
    setTimeout(async () => {
      const GMap = await import('./GMap/index');
      GMap.default('.js-map', process.env.GOOGLE_MAPS_API_KEY)
    }, 0);
  }
}

async function concurrentStart() {
  const map = loadMap();
  InfoComponent.init();
  SelectBuilder.init();
  FilterBuilder.init();
  window.onload = async function () {
    const lightButton = document.querySelector('.light-icon');
    const changeTheme = await import('./themeSelector');
    lightButton.addEventListener('click', changeTheme.default, { capture: true, passive: true });  
  };

  await map;
}
concurrentStart();

但是,我在运行灯塔审计时一直得到相同的结果。在不阻塞应用程序其余代码的情况下加载 map 的正确方法是什么?

最佳答案

Lighthouse 会一直等到事件循环中没有任何任务为止,因此您将 setTimeout 设置的时间越长,您获得的排名就越低。 Check this out

我只是让浏览器来做肮脏的工作。 只需添加脚本,并使用它的异步/延迟属性

这里是关于 async / defer 的更多信息关于 event loop

同时考虑使用其他性能工具,例如 https://developers.google.com/speedhttps://www.webpagetest.org/

如果它很关键,您可以仅在它可见时通过使用滚动事件或交叉点观察器加载库,但灯塔很可能不会感觉到任何改进,上面的在线工具会做。

关于javascript - 在 onload 事件上加载谷歌地图仍然会在页面加载后给出加载它的灯塔消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61631596/

相关文章:

javascript - 在使用 Fusion Table 创建的 map 中创建指向 map 标记的链接

java - 有没有办法避免 Jackson 序列化未获取的惰性属性

javascript - 内容可见性自动与延迟加载内容性能

javascript - 如何访问数组中对象中的 img 标签的属性?

javascript - 将数组的大小/长度减少到一定的大小/长度

javascript - 计数、间隔和事件的响应式扩展缓冲区

javascript - 多边形中的点检查纬度和经度值

javascript - 范围 slider - 如何在填充时更改刻度颜色?

google-maps - Google Maps API v3 删除所有折线

java - 为什么 Hibernate Open Session in View 被认为是不好的做法?