Webpack - метод DefinePlugin

В определениях для плагина webpack, я пытаюсь предоставить функцию переопределения, которую мой модуль будет получать, если метод существует.

export const listFetchAPI = () => {
  return ( LIST_FETCH_API ? LIST_FETCH_API : '/list/');
};
export const listFetchTX = (data) => {
  return ( LIST_FETCH_TX === 'function' ? LIST_FETCH_TX(data) : data );
};

В моей конфигурации webpack, основанной на среде или реализации проекта, я могу или не хочу предоставлять переопределения для этих функций.

webpackConfig.plugins.push(
  new webpack.DefinePlugin({
    LIST_FETCH_API: JSON.stringify('https://testapi.com/listFetch/')
    LIST_FETCH_TX(data) { return { ...data, test: 'HELLO!' }; }
  })
);  

Я пробовал как с обозначениями ES5, так и с ES6. Когда я строю, я получаю сообщение об ошибке SyntaxError: Unexpected identifier

Я не вижу в документах, где вы можете передать метод через DefinePlugin. https://webpack.js.org/plugins/define-plugin/

Поиск Google подходит для nill. Следующим шагом было бы передать строковое значение, а затем использовать react-json-schema для подбора компонента. Это кажется слишком вовлеченным, поэтому я надеюсь найти способ определения методов в DefinePlugin.

ИЗМЕНИТЬ Для пояснения, что я делаю, создается общий модуль редукции, который может быть зарегистрирован в частном реестре npm. При вызове этому модулю могут быть предоставлены переопределения для URL-адресов API-адресов и ответных переводчиков. Это мешает мне разветвлять код или создавать модули, которые на 99% похожи каждый раз, когда я устанавливаю для другого поставщика.

Если передача функций через переменную окружения не подходит, каким будет альтернативный метод для таких переопределений? Я не уверен, что объект конфигурации разыгрывается, когда вещи отправляются через магазин. Другой вариант, с которым я играю, - это переопределение всех файлов в модуле. Я знаком с методами Ruby с использованием import_path, но в исследовании я не видел эквивалентных методов JS/npm.

Ответ 1

DefinePlugin - это прямая замена текста, аналогичная макросам в C. Webpack будет искать идентификатор и заменять его на заданную строку. Следующий пример иллюстрирует, как это работает.

Со следующей конфигурацией плагинов

new webpack.DefinePlugin({
  VAR: 'myVar',
  STRING: '"a string (note the quotes inside quotes)"',
  FUNCTION: 'function myFun(arg) { console.log("myFun was called with", arg); }'
})

и JavaScript в качестве входных данных:

const myVar = 'hello';

console.log(VAR);
console.log(STRING);
console.log(FUNCTION);
// IIFE requires parens to execute
(FUNCTION)('iife');

// Better, only defines the function once
const functionToCall = FUNCTION;
functionToCall('another arg');

Выходной JavaScript будет:

const myVar = 'hello';

console.log(myVar);
console.log("a string (note the quotes inside quotes)");
console.log(function myFun(arg) { console.log("myFun was called with", arg); });
// IIFE requires parens to execute
(function myFun(arg) { console.log("myFun was called with", arg); })('iife');

// Better, only defines the function once
const functionToCall = function myFun(arg) { console.log("myFun was called with", arg); };
functionToCall('another arg');

Как вы можете видеть, они просто были заменены значениями, определенными в DefinePlugin. Если вы запустите его, вы получите следующий журнал консоли:

hello
a string (note the quotes inside quotes)
[Function: myFun]
myFun was called with iife
myFun was called with another arg

Для STRING вы обычно используете JSON.stringify(), который просто дает строковое представление строки (кавычки внутри кавычек). Если вы этого не сделаете, это будет просто идентификатор, и если идентификатор не был определен, он выдаст ошибку. FUNCTION также показывает, что он будет заменен повсюду, он не ссылается на одну и ту же функцию, потому что это прямая замена текста.


Если вы хотите опционально определить что-то, вам также необходимо проверить, существует ли переменная, потому что, если вы этого не сделаете, она выдает ошибку.

const varOrDefault = typeof VAR !== 'undefined' ?  VAR : 'default'; 

Вы не можете сделать VAR === undefined, потому что предполагается, что переменная существует, и будет проверять, является ли она undefined, но когда она вообще не определена, она выдает ошибку, которая не определена VAR. После этого вы можете свободно использовать переменную и использовать ее так, как вы хотели, и проверить, является ли она функцией или нет (при проверке функции вы можете пропустить тест, был ли он определен, потому что в любом случае он будет использовать typeof).

Честно говоря, это не очень хорошее решение, тем более, что функция будет включена дважды из-за необходимой проверки typeof. И, честно говоря, такая замена текста не подходит для условно определенной динамической структуры. Было бы гораздо лучше переместить это в объект конфигурации. Очень просто принять объект конфигурации и указать значения по умолчанию. Существует несколько способов сделать это.

Например, Object.assign:

function mainFunction(options) {
  const defaults = { /* default values */ };
  options = Object.assign({}, defaults, options);

  // Use the options later
}

Ответ 2

Согласно документации DefinePlugin

DefinePlugin позволяет создавать глобальные константы, которые могут быть настроен во время компиляции. Это может быть полезно для поведение между сборками разработки и выпусками.

Эти определения являются парами ключевых значений в следующей строке синтаксиса кода. Ключ. Следует соблюдать значение.

Key : Value

 LIST_FETCH_TX(data) { return { ...data, test: 'HELLO!' }; }

Тем не менее я не уверен, что он будет работать для функции, поскольку целью является создание глобальных констант. Это может измениться в будущем, но новый материал продолжает: -)

Не уверен, что это ответы, но может помочь вам понять, почему он бросает ошибку с этим: missing.

Приветствия!