繁体   English   中英

页面加载后在 React 中加载第三方 iframe,使 iframe 不影响 PageSpeed 得分

[英]Load third party iframe in React after page load, so that the iframe does not affect PageSpeed score

我有一个加载第三方小部件的iframe 我只想在我的页面加载后显示这个iframe ,因为我不想减慢我的页面加载速度。 我关注了一篇描述如何执行此操作的中型文章,但他们的解决方案不起作用,因为从未调用过加载onloadfinishLoading

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 后(使用积极效果)并没有太多在 PageSpeed 上。


如果它有帮助,域名是突然的sask.com,第三方小部件是亚马逊广告。

更新

我访问了该网站,我确定您使用的是 Gatsby。 Gatsby 正在使用 SSR,React.lazy 和 Suspense 还不能用于服务器端渲染。 如果您想在服务器渲染的应用程序中进行代码拆分,建议在React 文档中使用可加载组件 它有一个很好的使用服务器端渲染进行捆绑拆分的指南

有一个 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 Code-Splitting 是 Webpack、Rollup 和 Browserify(通过 factor-bundle)等捆绑器支持的功能,它可以创建多个可以在运行时动态加载的捆绑包。

如果你正在使用 Create React App,这已经为你配置好了,你可以立即开始使用它。

对你的应用程序进行代码拆分可以帮助你“延迟加载”用户当前需要的东西,这可以显着提高你的应用程序的性能。 虽然您没有减少应用程序中的代码总量,但您避免了加载用户可能永远不需要的代码,并减少了初始加载期间所需的代码量。

这是您的问题的示例解决方案,它将延迟加载亚马逊广告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;

Google PageSpeed/Lighthouse 不仅分析网站的 static 内容,因为它是在评估性能时从服务器发送的。 由于这里演示的大多数技术都尽可能快地加载 iframe(即,只要调用了useEffect挂钩),您最终会在页面速度测量时间段内引发 CPU 和网络请求。

这里有几种方法可以减少 iframe 对您的分数的影响。 可能很难提前说会产生什么影响,因为它取决于连接/网络和服务器性能——您需要测试和试验以获得最佳结果。

  1. 在 iframe 上使用loading="lazy" 这将指示浏览器在接近视口之前不要加载它(例如,如果它在折叠下方,则在用户向下滚动之前它根本不会加载)。
  2. 在 useEffect 中设置超时以将useEffect的加载延迟固定持续时间,从而降低在页面速度测量 window 期间发生这种情况的可能性。 例如:
     const [ready, setReady] = useState(false) useEffect(() => { setTimeout(() => { setReady(true) }, 3000) }, []) return (<iframe src={ready? "/your/url": "about:blank"} loading="lazy" />)
  3. 与#2 类似,仅侦听页面上的交互事件(例如滚动或点击),并且仅在该事件发生后才加载广告。

iframe 永远不会加载!

React 不会首先安装 iframe,因为它是有条件地安装的( loading ),并且条件永远不会改变,因为它依赖于安装的 iframe。

您可以在 react 外部加载 iframe 并将其附加到useEffect挂钩中:

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 会加载外部内容。 但是你可以试一试。

你必须使用useEffect()钩子。

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

在这种情况下stillLoading(false)将仅在组件安装后应用。 因此,最后您的条件将在加载页面后起作用。

您可以使用 window.onload function 在运行时加载 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 元素指向空白,并且可以在运行时更改 src。

<iframe id="my-deferred-iframe" src="about:blank" />

最近添加了一个新属性,可提高 iframe 的性能。 它被称为加载,它可以有 2 个值指示浏览器应如何加载 iframe:急切(立即加载 iframe)和懒惰(延迟加载 iframe 直到它达到与视口的计算距离)。 因此,它将类似于: <iframe src={src} loading="eager"/> 在此处阅读更多信息

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM