Загружать сторонние iframe в React после загрузки страницы, чтобы iframe не влиял на оценку PageSpeed - PullRequest
3 голосов
/ 13 июля 2020

У меня есть iframe, который загружает сторонний виджет. Я хочу отображать это iframe только после загрузки моей страницы, потому что я не хочу замедлять скорость загрузки моей страницы. Я следил за статьей medium , в которой описывается, как это сделать, но их решение не работает, потому что функция onload, finishLoading, никогда не вызывается

export default ({src, width, height}) => {

  const [loading, stillLoading] = useState(true)
  const finishLoading = () => {
      alert('finished loading')
      stillLoading(false)
  }
  ...
  return(
    {loading ? '' : 
      <iframe
        src={src}
        width={width}
        height={height}
        scrolling="no"
        onLoad={finishLoading}
      >
        className={`tpwidget flex-center-row`}>
      </iframe>
    }
  )
}

Обновление

Используя useEffect, я могу заставить iframe загружаться после всего остального (теоретически), но я обнаружил, что удаление iframe полностью улучшает мою оценку PageSpeed, и это просто загрузка iframe после (с использованием useEffect) не оказывает большого положительного влияния на PageSpeed.

Если это поможет, то домен будет внезапноsask.com , а сторонний виджет - это реклама Amazon.

Ответы [ 5 ]

2 голосов
/ 29 июля 2020

Google PageSpeed ​​/ Lighthouse не просто анализирует c статистическое содержание сайта, которое отправляется с сервера при оценке производительности. Поскольку большинство методов, продемонстрированных здесь, загружают iframe как можно быстрее (т. Е. Как только вызывается ловушка useEffect), в течение периода измерения скорости страницы вы получаете запрос к ЦП и сети.

Вот несколько способов уменьшить влияние iframe на ваш счет. Трудно сказать заранее, какое влияние будет оказано, поскольку оно зависит от соединения / сети и производительности сервера - вы захотите протестировать и поэкспериментировать, чтобы получить наилучшие результаты.

  1. Используйте loading="lazy" в iframe. Это даст указание браузеру не загружать его, пока он не приблизится к области просмотра (например, если он находится ниже сгиба, он не будет загружаться вообще, пока пользователь не прокрутит вниз).
  2. Установите тайм-аут в useEffect чтобы отложить загрузку iframe на фиксированную продолжительность, уменьшая вероятность того, что это произойдет во время вашего окна измерения скорости страницы. Например:
    const [ready, setReady] = useState(false)
    useEffect(() => { setTimeout(() => { setReady(true) }, 3000) }, [])
    return (<iframe src={ready ? "/your/url" : "about:blank"} loading="lazy" />)
    
  3. Аналогично # 2, только прослушивать событие взаимодействия (например, прокрутку или щелчок) на странице и загружать рекламу только после того, как это событие произошло.
2 голосов
/ 23 июля 2020

Обновление

Я посетил веб-сайт и уверен, что вы используете Gatsby. Gatsby использует SSR, а React.lazy и Suspense еще не доступны для рендеринга на стороне сервера. Если вы хотите выполнить разделение кода в приложении, отображаемом на сервере, рекомендуется Загружаемые компоненты в React docs . В нем есть прекрасное руководство по разделению пакетов с рендерингом на стороне сервера .

Есть плагин gatsby, чтобы облегчить вашу жизнь gatsby-plugin-loadable-components-ssr . После установки и настройки плагина вы можете использовать loadable следующим образом:

AmazonFrame.js

import React from "react";

const AmazonFrame = ({ src, width, height }) => (
  <iframe src={src} width={width} height={height} scrolling="no"></iframe>
);

App.js

import React from "react";
import loadable from "@loadable/component";

const AmazonFrame = loadable(() => import("./AmazonFrame"), {
  fallback: <div>Loading...</div>
});

function App() {
  return (
    <div>
      <AmazonFrame src="src" width="100%" height="200px" />
    </div>
  );
}

export default App;

или

import React from "react";
import loadable from "@loadable/component";

const AmazonFrame = loadable(() => import("./AmazonFrame"));

function App() {
  return (
    <div>
      <AmazonFrame fallback={<div>Loading...</div>} />
    </div>
  );
}

export default App;

Исходный ответ

Вам нужно использовать Code-Splitting . Разделение кода - это функция, поддерживаемая такими сборщиками, как Webpack, Rollup и Browserify (через factor-bundle), которые могут создавать несколько пакетов, которые могут динамически загружаться во время выполнения.

Если вы используете приложение Create React, это уже настроено для вас, и вы можете начать его использовать немедленно.

Разделение кода вашего приложения может помочь вам «отложить загрузку» только тех вещей, которые в настоящее время необходимы пользователю, что может значительно повысить производительность вашего приложения. Хотя вы не уменьшили общий объем кода в своем приложении, вы избежали загрузки кода, который может никогда не понадобиться пользователю, и уменьшили количество кода, необходимого во время начальной загрузки.

Вот пример решение вашей проблемы, которое будет лениво загружать рекламу Amazon iframe, поэтому она не будет загружена с вашим начальным пакетом:

AmazonFrame.js

import React from "react";

const AmazonFrame = ({ src, width, height }) => (
  <iframe src={src} width={width} height={height} scrolling="no"></iframe>
);

export default AmazonFrame;

App.js

import React, { Suspense, lazy } from "react";

// React.lazy takes a function that must call a dynamic import(). This must return a Promise
// which resolves to a module with a default export containing a React component.
const AmazonFrame = lazy(() => import("./AmazonFrame"));
function App() {
  return (
    <div>
      {/* The lazy component should then be rendered inside a Suspense component, which allows us to show some fallback
       content (such as a loading indicator) while we’re waiting for the lazy component to load */}
      {/* The fallback prop accepts any React elements that you want to render while waiting for the component to load */}
      <Suspense fallback={<div>Loading...</div>}>
        <AmazonFrame src="src" width="100%" height="200px" />
      </Suspense>
    </div>
  );
}

export default App;
1 голос
/ 23 июля 2020

iframe никогда не загружается!

React не будет монтировать iframe в первую очередь, поскольку он установлен условно (loading), и условие никогда не меняется, поскольку оно зависит от монтируемого iframe.

Вы можете загрузить iframe за пределами React и прикрепить его с помощью useEffect hook:

export default ({src, width, height}) => {

    const container = useRef()
    useEffect(() => {
        const frm = document.createElement('iframe')
        frm.src = src
        frm.width = width
        frm.height = height
        frm.scrolling = 'no'
        container.current.appendChild(frm)
    }, [])

    return(
        <div ref={container} />
    )
}

При этом я не могу сказать вам, ускорит ли это загрузку страницы, в конце концов , iframe загружают внешний контент. Но вы можете попробовать.

0 голосов
/ 27 июля 2020

Вы можете использовать функцию window.onload для загрузки iframe во время выполнения.

function loadDeferredIframe() {
    // this function will load the Google homepage into the iframe
    var iframe = document.getElementById("my-deferred-iframe");
    iframe.src = "./" // here goes your url
};
window.onload = loadDeferredIframe;

Сначала у вас может быть элемент iframe, указывающий на пустой, и вы можете изменить sr c во время выполнения.

<iframe id="my-deferred-iframe" src="about:blank" />
0 голосов
/ 13 июля 2020

Вы должны использовать useEffect() хук.

useEffect(() => {
  stillLoading(false)
}, [])

В этом случае stillLoading(false) будет применяться только после того, как компонент будет смонтирован. Итак, в конце ваше условие будет работать после загрузки страницы.

...