我有一个问题, gatsby developgatsby build 生成的网站之间的行为不一致 . 结果是一个在开发中工作而不是 生产环境 的站点 .

我的网站摘要:

一个简单的类似博客的网站( Profiles 而不是博客文章) . 索引页面是人员列表,该列表中的每个项目都链接到该人员的 Profiles 页面 .

我正在使用Gatsby来构建网站 . 我的数据( Profiles )是Contentful无头CMS上托管的条目 . 我正在使用gatsby-source-contentful源插件 .

问题的高级描述

我无法改变索引页面上的配置文件列表项的顺序 . 我的网站超越任何基本的gatsby教程的唯一行为是我想在我的索引页面上随机化配置文件列表(让每个人都有一个公平的机会被列在顶部) .

gatsby build 生成一个静态索引页面,列表在一个排列中 . 当在浏览器中加载时, ThumbList 组件将这些项重新混洗到渲染上的另一个排列,并且一些子元素没有通过反应进行适当管理,并在其他元素移位时保持卡住状态 . 例如,这导致配置与错误名称配对的图像 .

代码

为了便于阅读,以下代码进行了总结 .

SRC /页/ index.js:

import React from "react"
import Layout from "../components/layout"
import ThumbList from "../components/thumbList"
import { graphql } from "gatsby"

export default ({data}) => {
  // people are called "creators" in the app
  const creatorData = data.allContentfulCreator.edges
  const shuffledData = shuffle(creatorData.slice(0))
    return (
      <Layout>
        <ThumbList data={shuffledData} />
      </Layout>
    )
}

const shuffle = (a) => {
  // Fisher-Yates randomized array in-place shuffle algo
  // ...
  return a
}

export const query = graphql`
  {
    allContentfulCreator {
      edges {
        node {
          id
          slug
          name
          bio {
            id
            bio
          }
          mainImage {
            file {
              url
            }
          }
        }
      }
    }
  }
`

SRC /组件/ thumbList.js:

import React from "react"
import { Link } from "gatsby"

// A list of creator profile links, with name and picture thumbnail
export default ({data}) => {
  return (
    <div>
      <ul>
        {
          data.map(({node}) => {
            const creator = node
            const link = "/" + creator.slug
            const image = "https:" + creator.mainImage.file.url

            return (
              <li key={creator.id}>
                <Link to={link}>
                  {creator.name}
                </Link>
                <img src={image} />
              </li>
            )
          })
        }
      </ul>
    </div>
  )
}

gatsby build 的结果是 index.html ,其中包含:

<ul>
    <li>
      <a href="/alice">
        Alice
      </a>
      <img src="cdn.com/alice.jpg">
    </li>
    <li>
      <a href="/bob">
        Bob
      </a>
      <img src="cdn.com/bob.jpg">
    </li>
    <li>
      <a href="/eve">
        Eve
      </a>
      <img src="cdn.com/eve.jpg">
    </li>
  </ul>

但是,在浏览器中查看索引页面时(通过 gatsby serve 或站点的已部署版本),live react ThumbList 组件会再次在其render方法中对数据进行洗牌 .

结果重新渲染了html:

<ul>
    <li>
      <a href="/alice">
        Bob
      </a>
      <img src="cdn.com/alice.jpg">
    </li>
    <li>
      <a href="/bob">
        Eve
      </a>
      <img src="cdn.com/bob.jpg">
    </li>
    <li>
      <a href="/eve">
        Alice
      </a>
      <img src="cdn.com/eve.jpg">
    </li>
  </ul>

这里只重新排列文本节点以匹配新的顺序(由控制台记录数组顺序确认),但链接和图像元素仍然停留在静态构建中的位置 . 现在名称,图像和链接都被扰乱了 .

还有两点需要注意:

  • 一切正常 gatsby develop . 我想这是因为在开发中,index.html是在没有静态内容的情况下生成的 - 允许从一开始就完全控制DOM,没有静态的脚手架来混淆它 .

  • 使用react检查器我发现虚拟DOM和真正的DOM已经不同步了 . React认为它已经正确地改组了列表项 . 检查员显示如下内容:

(非常简略,可读性)

<ul>
    <li key="165e2405">
        <GatsbyLink to="/bob">
            Bob
        </GatsbyLink>
        <img src="cdn.com/bob.jpg"></img>
    </li>
    <li key="067f9afc">
        <GatsbyLink to="/eve">
            Eve
        </GatsbyLink>
        <img src="cdn.com/eve.jpg"></img>
    </li>
    <li key="ca4b82bf">
        <GatsbyLink to="/alice">
            Alice
        </GatsbyLink>
        <img src="cdn.com/alice.jpg"></img>
    </li>
</ul>

我的问题

  • 这只是一种非盖茨比的做法吗? This description of a "Hybrid app page"似乎暗示您可以拥有静态或动态组件 . 我想我正在尝试两种方式:我希望在构建过程中通过graphql从内容中获取配置文件,这样它可以通过静态HTML预构建的json数据文件(例如 /static/d/556/path---index-6a9-L7r5Sntxcv3RUIoHYIR3Qqm9Jmg.json )获得,但后来我想动态地将其移除数据并在渲染时重新排列DOM . 盖茨比不可能做到这一点吗?我是否需要在构建期间放弃预先获取的数据,并且只考虑动态组件并通过 componentDidMount 中的Contentful API获取数据?

  • 如果这种方法应该没问题,我做错了什么?

  • 如果这种方法不是idomatic,有没有办法在构建时修改(shuffle)通过graphql查询的数据?如果数据仅在构建时拖曳并且在浏览器中没有在运行时重新洗牌,我实际上会更高兴 - 我可以自动化网站每小时左右重建一次,并且网站可能对客户端更加静态 .