GatsbyJS优化了何时提取图像

时间:2019-01-30 19:45:32

标签: gatsby

我喜欢盖茨比提供的所有优化功能,但是我希望对何时提取图像有更多的控制权。我该如何实现?

作为一个例子,考虑一个典型的博客:很多页面,很多文本,很少图片。

Gatsby中的默认行为是,当您滚动到带有占位符并进行过渡的图像时,图像会被懒加载(请转到任何Medium博客以查看其外观)。我不喜欢这样如果我在30秒钟前加载页面,那么已经有足够的时间向我发送图像了。没必要给我看一张模糊的照片,现在我应该有了真实的图像。

如何更改此行为?我在docs中发现的唯一内容是,我可以将图像标记为关键图像,以便它们立即开始加载。将我的所有图像标记为关键图像将是不好的,原因有两个:首先,它会减慢初始的“ First Meanfulful Paint”,因为浪费一部分带宽来加载页面下方的图像。其次,当预取到其他页面的链接时,再次浪费带宽下载大型图像。

在我的情况下,

期望的行为是先加载页面的关键资源,然后再加载页面的非关键资源。在预取链接时,不应加载非关键资源。


编辑:在Cyril和Derek的帮助下,我现在可以在超时的情况下获取图像。现在我有一个奇怪的问题:

https://epic-haibt-d9fc0a.netlify.com/

对于随时间获取的图像,好像“占位符”和“实际图像”的含义被翻转了。来源here的相关部分。

2 个答案:

答案 0 :(得分:2)

您可以扩展现有的React类并修改其行为。我深入研究了gatsby-image的来源,看起来道具isVisible负责加载图像。

可以确定地说,一旦文档完全装入,“ First Meanfulful Paint”就完成了吗?如果是这样,我认为我们可以使用window.onload作为触发来加载图像。

您可以像这样扩展现有的类:

import Image from 'gatsby-image'

class ImageDelay extends Image {
  componentDidMount() {

    // call the parent class' componentDidMount method
    // to preserve existing behavior
    super.componentDidMount();

    window.onload = () => {
      this.setState({
        isVisible: true
      })
    }
  }
}

export default ImageDelay

然后将其用作普通的Image组件:

import ImageDelay from '../components/ImageDelay'

// somewhere on your page
<ImageDelay fluid={heroFluid} />

您还可以使用setTimeout而不是window.onload添加延迟。如果用户在一定时间内没有滚动到图像,则会为其加载图像。

答案 1 :(得分:2)

由于基类构造函数具有一个props参数,因此添加构造函数会出错。

使用参数调用基本构造函数将解决此错误

constructor(props) {
    super(props);
    this.loadPictures = this.loadPictures.bind(this);
}

由于gatsby使用服务器端渲染 windowdocument时应谨慎使用。请参阅:https://www.gatsbyjs.org/docs/debugging-html-builds/https://github.com/gatsbyjs/gatsby/issues/5835。您应该先检查windowdocument对象是否存在,然后再取消订阅该事件,以避免内存泄漏。

class PictureDelay extends Picture {
  constructor(props) {
    super(props);
    this.loadPictures = this.loadPictures.bind(this);
  }

  loadPictures() {
    console.log("Loading pictures...");
    this.setState({ isVisible: true });
  }

  componentDidMount() {
    super.componentDidMount();

    if (typeof window !== "undefined") {
      window.addEventListener("load", this.loadPictures);
      // window.setTimeout(this.loadPictures, 1000);
    }
  }
  componentWillUnmount() {
    super.componentWillUnmount();
    if (typeof window !== "undefined") {
      window.removeEventListener("load", this.loadPictures);
    }
  }
}

使用gatsby链接时,不会重新加载页面。为了提高性能, Gatsby 使用内部机制来更新页面,并且在页面更新后不会触发window.load事件,也不会触发任何事件。  参见#2906 - gatsby-link determine when loading is complete#3415 - formalize API for hooking into page load lifecycle...

此外,不能保证inheritance is generally avoided in React application和依靠内部行为(isLoaded状态)在将来的版本中也可以使用。基于这些原因,我认为最好使用critical属性或创建自己的gatsby-image实现。

class PictureDelay extends React.Component {
  render() {
    return <Picture critical={true} {...this.props} />;
  }
}