获取远程图像并将其转换为gatsby图像

时间:2019-04-21 00:45:10

标签: reactjs graphql gatsby

我正试图从WP中获取一些图像,因为盖茨比目前还不能与woocommerece一起使用。我下面的插件能够转换图像,并在构建时将其添加到.cache,但是它没有在Gatsby graphQl内添加localFile___NODE字段。它似乎根本没有添加任何节点供我使用ImageSharp插件查询。 Graphql显示它们是在ALLFiles下处理的,但不在我在Graphql中创建的wcProduct节点中处理的。这是怎么回事,该插件不再创建节点了。

const utils = require("./utils")
const fetch = require("node-fetch")
const queryString = require("query-string")
const fs = require("fs-extra")
const { createRemoteFileNode } = require(`gatsby-source-filesystem`)

exports.sourceNodes = async (
  {
    actions, createNodeId, createContentDigest, store, cache
  },
  configOptions
) => {
  const { createNode } = actions

  await fs.removeSync("/.cache")

  // Gatsby adds a configOption that's not needed for this plugin, delete it
  delete configOptions.plugins

  // Helper function that processes a product to match Gatsby's node structure
  const processProduct = async (product, args) => {
    // console.log("product", product)

    //  https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-source-filesystem#createremotefilenode
    // download and add image to local file
    await product.images.map(async image => {

      const fileNode = await createRemoteFileNode({
        ...args,
        url: image.fullSize.url
      })
      image.localFile___NODE = fileNode.id

    })

    const nodeId = createNodeId(`wc-product-${product.id}`)
    const nodeContent = JSON.stringify(product)

    // Node info
    return Object.assign({}, product, {
      id: nodeId,
      parent: null,
      children: [],
      internal: {
        type: `wcProduct`,
        content: nodeContent,
        contentDigest: createContentDigest(product)
      }
    })
  }

  const apiUrl = `${process.env.GATSBY_DB}/wp-json/et-shop/graphql/products`
  const apiResponse = await fetch(apiUrl)
  const results = await apiResponse.json()
  const jsonResults = JSON.stringify(utils.transformNormalizedData(results.data))
  fs.writeFileSync("src/state/products.json", jsonResults)

  results.data.forEach(async (product) => {
    // Process the product data to match the structure of a Gatsby node
    const productNode = await processProduct(product, { store, cache, createNode, createNodeId })

    // Use Gatsby's createNode helper to create a node from the node data
    createNode(productNode)
  })
}

1 个答案:

答案 0 :(得分:1)

我意识到我没有正确编写异步循环。此代码使您可以从远程源中提取数据,然后在要转换为GraphQL的数据中添加一个节点。对我来说,我希望将图片网址转换为在盖茨比和ImageSharp插件中使用的图片。这将从我的CMS中获取该图像,并将其转换为“ Gatsby图像”,可以在wcProduct.images.localFile下的graphQL查询中找到

const utils = require("./utils")
const fetch = require("node-fetch")
const fs = require("fs-extra")
const { createRemoteFileNode } = require(`gatsby-source-filesystem`)

exports.sourceNodes = async (
  {
    actions, createNodeId, createContentDigest, store, cache
  },
  configOptions
) => {
  const { createNode } = actions

  await fs.removeSync("/.cache")

  // Gatsby adds a configOption that's not needed for this plugin, delete it
  delete configOptions.plugins

  // Helper function that processes a product to match Gatsby's node structure
  const processProduct = async (product, args) => {

    // https://flaviocopes.com/javascript-async-await-array-map/
    product.images = await Promise.all(product.images.map(async image => {
      let fileNode

      try {
        fileNode = await createRemoteFileNode({
          url: image.fullSize.url,
          ...args
        })

      } catch (e) {
        console.log("e", e)

      }
      if (fileNode) {
        console.log("createdFile node")
        image.localFile___NODE = fileNode.id
        return image
      }
    }))

    const nodeId = createNodeId(`wc-product-${product.id}`)
    const nodeContent = JSON.stringify(product)

    // Node info
    return Object.assign({}, product, {
      id: nodeId,
      parent: null,
      children: [],
      internal: {
        type: `wcProduct`,
        content: nodeContent,
        contentDigest: createContentDigest(product)
      }
    })
  }

  const apiUrl = `${process.env.GATSBY_DB}/wp-json/et-shop/graphql/products`
  const apiResponse = await fetch(apiUrl)
  const results = await apiResponse.json()

  const jsonResults = JSON.stringify(utils.transformNormalizedData(results.data))
  fs.writeFileSync("src/state/products.json", jsonResults)

  await asyncForEach(results.data, async (product) => {
    const productNode = await processProduct(product, { store, cache, createNode, createNodeId })

    createNode(productNode)
  })
}

// https://codeburst.io/javascript-async-await-with-foreach-b6ba62bbf404
async function asyncForEach (array, callback) {
  for (let index = 0; index < array.length; index++) {
    await callback(array[index], index, array)
  }
}