加载google地图在onload事件中仍然给出灯塔信息,在页面加载后再加载。

问题描述 投票:0回答:1

我已经为我的项目运行了chrome审计,其中有人建议我减少第三方代码的影响。在我的例子中,我正在加载谷歌地图api。我是这样做的。

在我的main.js中,我检查了附加地图的元素。

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;

在运行审计后,我将地图的加载改为在页面加载后进行。

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

但是,我仍然从chrome的灯塔得到同样的审计信息。

enter image description here

你可以看到一个工作实例 此处.

更新

我也试过用async await逻辑加载地图,就像这样。

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();

但是,当我运行灯塔审计时,我一直得到同样的结果。有什么正确的方法可以在不阻塞应用的其他代码的情况下加载地图?

javascript google-maps lazy-loading
1个回答
2
投票

Lighthouse会一直等待,直到事件循环中没有一个任务,所以你设置的setTimeout时间越长,你的等级就会越低。看看这个

我会让浏览器来做这些肮脏的工作.只需添加脚本,并使用它的async defer属性。

在这里,你去与更多的信息 异步延时 以及关于 事件循环

也可以考虑使用其他性能工具,如 https:/developers.google.comspeedhttps:/www.webpagetest.org

如果很关键,你可以通过使用滚动事件或交汇点观察器,只在可见时加载lib,但很可能灯塔感觉不到任何改进,上面的在线工具就可以了。

© www.soinside.com 2019 - 2024. All rights reserved.