createSingleNode = async ({
  singleName,
  id,
  actionType,
  data,
  cachedNodeIds,
}) => {
  const state = getStore().getState()
  const { helpers, pluginOptions } = state.gatsbyApi
  const { wpUrl } = state.remoteSchema

  const { typeInfo } = getQueryInfoBySingleFieldName(singleName)

  if (!cachedNodeIds && needToTouchNodes) {
    cachedNodeIds = await getPersistentCache({ key: CREATED_NODE_IDS })
  }

  const updatedNodeContent = {
    ...data[singleName],
    nodeType: typeInfo.nodesTypeName,
    type: typeInfo.nodesTypeName,
  }

  const { processedNode, nodeMediaItemIdReferences } = await processNode({
    node: updatedNodeContent,
    pluginOptions,
    wpUrl,
    helpers,
  })

  await fetchReferencedMediaItemsAndCreateNodes({
    referencedMediaItemNodeIds: nodeMediaItemIdReferences,
  })

  const { actions } = helpers

  const { createContentDigest } = helpers

  const builtTypename = buildTypeName(typeInfo.nodesTypeName)

  let remoteNode = addImageCDNFieldsToNode(
    {
      ...processedNode,
      __typename: builtTypename,
      id: id,
      parent: null,
      internal: {
        contentDigest: createContentDigest(updatedNodeContent),
        type: builtTypename,
      },
    },
    pluginOptions
  )

  const typeSettings = getTypeSettingsByType({
    name: typeInfo.nodesTypeName,
  })

  let additionalNodeIds = nodeMediaItemIdReferences || []
  let cancelUpdate

  if (
    typeSettings.beforeChangeNode &&
    typeof typeSettings.beforeChangeNode === `function`
  ) {
    const {
      additionalNodeIds: receivedAdditionalNodeIds,
      remoteNode: receivedRemoteNode,
      cancelUpdate: receivedCancelUpdate,
    } = (await typeSettings.beforeChangeNode({
      actionType: actionType,
      remoteNode,
      actions,
      helpers,
      fetchGraphql,
      typeSettings,
      buildTypeName,
      type: typeInfo.nodesTypeName,
      wpStore: getStore(),
    })) || {}

    additionalNodeIds = [
      ...additionalNodeIds,
      ...(receivedAdditionalNodeIds || []),
    ]

    cancelUpdate = receivedCancelUpdate

    if (receivedRemoteNode) {
      remoteNode = receivedRemoteNode
    }
  }

  if (cancelUpdate) {
    return {
      additionalNodeIds,
      remoteNode: null,
    }
  }

  if (remoteNode) {
    actions.createNode(remoteNode)
  }

  if (remoteNode && needToTouchNodes) {
    cachedNodeIds.push(remoteNode.id)
    additionalNodeIds?.forEach(id => cachedNodeIds.push(id))

    await setPersistentCache({ key: CREATED_NODE_IDS, value: cachedNodeIds })
  }

  return { additionalNodeIds, node: remoteNode }
}
For Preview, revisions of a node type can have data that updates unecessarily
This code block fixes that. The result being that less queries
are invalidated in Gatsby. For example if you have a query where you're getting the latest published post using the date field, that should be static but each preview updates the date field on the node being previewed (because the revision has a new date). So if we prevent the following fields from changing, this will be less problematic.