Как я могу получить динамические данные из gatsby-config.js?

Рассмотрим следующий код в 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,
      },
    },
  ],
}

Как вы можете видеть выше, мне нужно, чтобы URL-адрес исходного плагина был динамическим. Причина в том, что URL-адрес файла будет изменяться каждый раз, когда он обновляется в CMS. Мне нужно запросить CMS для этого поля и получить его URL-адрес CDN, прежде чем переходить к плагину.

Я попытался добавить следующее в начало 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
})()

Я предполагаю, что это не сработает, потому что конфигурация не ожидает разрешения вышеуказанного запроса и, следовательно, все, что мы получаем, - это пустой URL-адрес.

Есть ли лучший способ сделать это? Я не могу просто заранее предоставить исходному плагину фиксированный / известный URL.

Любая помощь очень ценится. Обычно я использую Vue.js, но мне приходится работать с React / Gatsby, поэтому я не совсем с ним знаком.


person Michael Giovanni Pumo    schedule 20.08.2020    source источник


Ответы (2)


У меня было аналогичное требование, когда мне нужно динамически устанавливать siteId для gatsby-plugin-matomo, извлекая данные из async api. После поиска в документации по жизненному циклу сборки gatsby я нашел решение.

Вот мой подход -

gatsby-config.js

module.exports = {
   siteMetadata: {
     ...
   },
   plugins: {
     {
        resolve: 'gatsby-plugin-matomo',
        options: {
           siteId: '',
           matomoUrl: 'MATOMO_URL',
           siteUrl: 'GATSBY_SITE_URL',
           dev: true
        }
      }
    }
};

Здесь 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 */
};

onPreInit - это метод жизненного цикла gatsby, который выполняется сразу после загрузки плагина из config. У ловушки жизненного цикла onPreInit есть несколько встроенных методов.

store - это хранилище redux, в котором Гэтсби хранит всю необходимую информацию для процесса сборки.

setPluginStatus - это действие redux, с помощью которого данные плагина могут быть изменены в хранилище redux gatsby.

Здесь важно то, что ловушка жизненного цикла onPreInit должна вызываться асинхронно.

Надеюсь, это поможет кому-то в будущем.

person Abhisek Bera    schedule 29.01.2021
comment
Мне нужно было сделать это для диспетчера тегов Google. Хочу отметить, что строка plugin.pluginOptions = {...plugin.pluginOptions, ...{ siteId: matomo_site_id }}; не является обязательной. plugin.pluginOptions необходимо изменить, чтобы он работал. Любопытно, что setPluginStatus можно удалить. - person Gabriel Vilches Alves; 05.05.2021

Другой подход, который может сработать для вас, - это использование переменных среды, как вы сказали, URL известно, поэтому вы можете добавить их в .env файл, а не в CSV.

По умолчанию Гэтсби использует .env.development для gatsby develop и .env.production для gatsby build команды. Поэтому вам нужно будет создать два файла в корне вашего проекта.

В вашем .env.env.development, и .env.production) просто добавьте:

DYNAMIC_URL: https://yourUrl.com

Поскольку ваш 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,
      },
    },
  ],

Важно избегать отслеживания этих файлов в вашем репозитории Git, поскольку вы не хотите раскрывать этот тип данных.

person Ferran Buireu    schedule 21.08.2020
comment
Спасибо за ваши усилия, но я думаю, вы просто переместили проблему на .env. Я говорю об использовании результата асинхронной операции для заполнения этого поля перед выполнением конфигурации. - person Michael Giovanni Pumo; 21.08.2020