如何从 gatsby-config.js 中获取动态数据?

Mic*_*umo 7 javascript reactjs gatsby

考虑以下代码gatsby-config.js

module.exports = {
  plugins: [
    {
      resolve: `gatsby-source-fetch`,
      options: {
        name: `brands`,
        type: `brands`,
        url: `${dynamicURL}`, // This is the part I need to be dynamic at run/build time.
        method: `get`,
        axiosConfig: {
          headers: { Accept: "text/csv" },
        },
        saveTo: `${__dirname}/src/data/brands-summary.csv`,
        createNodes: false,
      },
    },
  ],
}
Run Code Online (Sandbox Code Playgroud)

正如您在上面看到的,源插件的 URL 需要是动态的。原因是文件 URL每次在 CMS 中更新时都会发生变化。我需要在 CMS 中查询该字段并获取其 CDN URL,然后再传递给插件。

我尝试将以下内容添加到顶部gatsby-config.js,但出现错误。

const axios = require("axios")

let dynamicURL = ""
const getBrands = async () => {
  return await axios({
    method: "get",
    url: "https://some-proxy-url-that-returns-json-with-the-csv-file-url",
  })
}

;(async () => {
  const brands = await getBrands()
  dynamicURL = brands.data.summary.url
})()
Run Code Online (Sandbox Code Playgroud)

我假设这不起作用,因为配置没有等待上面的请求解析,因此,我们得到的只是一个空白 URL。

有没有更好的方法来做到这一点?我不能简单地提前为源插件提供固定/已知的 URL。

非常感谢任何帮助。我通常是一个 Vue.js 人员,但必须使用 React/Gatsby,所以我并不完全熟悉它。

小智 10

我有类似的要求,我需要通过从异步 api 获取数据来动态设置 gatsby-plugin-matomo 的 siteId 。在搜索了大量 gatsby 构建生命周期的文档后,我找到了解决方案。

这是我的方法 -

gatsby-config.js

module.exports = {
   siteMetadata: {
     ...
   },
   plugins: {
     {
        resolve: 'gatsby-plugin-matomo',
        options: {
           siteId: '',
           matomoUrl: 'MATOMO_URL',
           siteUrl: 'GATSBY_SITE_URL',
           dev: true
        }
      }
    }
};
Run Code Online (Sandbox Code Playgroud)

这里的 siteId 是空白的,因为我需要动态地放置它。

gatsby-node.js

exports.onPreInit = async ({ actions, store }) => {
    const { setPluginStatus } = actions;
    const state = store.getState();
    const plugin = state.flattenedPlugins.find(plugin => plugin.name === "gatsby-plugin-matomo");
    if (plugin) {
        const matomo_site_id = await fetchMatomoSiteId('API_ENDPOINT_URL');
        plugin.pluginOptions = {...plugin.pluginOptions, ...{ siteId: matomo_site_id }};
        setPluginStatus({ pluginOptions: plugin.pluginOptions }, plugin);
    }
};

exports.createPages = async function createPages({ actions, graphql }) {
    /* Create page code */
};
Run Code Online (Sandbox Code Playgroud)

onPreInit是一个 gatsby 生命周期方法,它在从配置加载插件后立即执行。onPreInit 生命周期挂钩有一些内置方法。

store是 redux 存储,gatsby 存储构建过程所需的所有信息。

setPluginStatus是一个 redux 操作,通过它可以在 gatsby 的 redux 存储中修改插件数据。

这里重要的是onPreInit生命周期钩子必须以异步方式调用。

希望这对将来的人有帮助。


Fer*_*reu 1

另一种可能对您有用的方法是使用您所说的环境变量,URL 是已知的,您可以将它们添加到文件.env而不是 CSV 中。

默认情况下,Gatsby 使用.env.developmentforgatsby develop.env.productionforgatsby build命令。因此,您需要在项目的根目录中创建两个文件。

在您的.env(和.env.development)中.env.production只需添加:

DYNAMIC_URL: https://yourUrl.com
Run Code Online (Sandbox Code Playgroud)

由于您的gatsby-config.js内容是在 Node 服务器中呈现的,因此您不需要GATSBY_像客户端需要的那样为它们添加前缀。所以,在你的gatsby-config.js

module.exports = {
  plugins: [
    {
      resolve: `gatsby-source-fetch`,
      options: {
        name: `brands`,
        type: `brands`,
        url: process.env.DYNAMIC_URL, // This is the part I need to be dynamic at run/build time.
        method: `get`,
        axiosConfig: {
          headers: { Accept: "text/csv" },
        },
        saveTo: `${__dirname}/src/data/brands-summary.csv`,
        createNodes: false,
      },
    },
  ],
Run Code Online (Sandbox Code Playgroud)

避免在 Git 存储库中跟踪这些文件非常重要,因为您不想公开此类数据。

  • 感谢您的努力,但我认为您只是将问题转移到了 .env。我正在谈论使用异步操作的结果,以便在配置执行之前填充此字段。 (2认同)