Загрузка карт Google при событии onload по-прежнему дает сообщение маяка для его загрузки после загрузки страницы - PullRequest
2 голосов
/ 06 мая 2020

Я провел аудит chrome для своего проекта, где мне предложили уменьшить влияние стороннего кода. В моем случае я загружаю API карт Google. Я делаю это так:

В моем 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

Вы можете увидеть рабочий пример здесь .

Обновление

Я также пытался загрузить карту с помощью asyn c await logi c вот так:

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

Но я продолжал получать тот же результат при запуске аудита маяков. Как правильно загрузить карту, не блокируя остальной код приложения?

1 Ответ

2 голосов
/ 14 мая 2020

Lighthouse будет ждать, пока в событии l oop не будет ни одной задачи, поэтому чем дольше вы установите setTimeout, тем более низкий ранг вы получите. Проверьте это

Я бы просто позволил браузеру делать всю грязную работу. Просто добавьте скрипт и используйте его атрибуты asyn c / defer

Здесь вы go с дополнительной информацией о asyn c / defer и о событии l oop

Рассмотрите возможность использования других инструментов повышения производительности, таких как https://developers.google.com/speed и https://www.webpagetest.org/

Если это критично , вы можете загрузить библиотеку только тогда, когда она видна с помощью событий прокрутки или наблюдателя пересечения, но вероятно, что Lighthouse не почувствует никаких улучшений, подойдут указанные выше онлайн-инструменты.

...