webpack - 定义插件方法 [英] webpack - DefinePlugin method

查看:25
本文介绍了webpack - 定义插件方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 webpack 插件的定义中,我试图提供一个覆盖函数,如果该方法存在,我的模块将选取该函数.

In the defintions for a webpack plugin, I'm trying to supply an override function that my module will pickup if the method exists.

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 配置中,基于项目的环境或实现,我可能想也可能不想为这些功能提供覆盖.

In my webpack config, based on the environment or implementation of the project, I may or may not want to supply overrides for these functions.

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

I've tried with both ES5 and ES6 notation. When I build, I get an error SyntaxError: Unexpected identifier

我在文档中没有看到您可以通过 DefinePlugin 传递方法.https://webpack.js.org/plugins/define-plugin/

I don't see in the docs where you can pass a method through the DefinePlugin. https://webpack.js.org/plugins/define-plugin/

Google 搜索结果为零.我的下一步是传递一个字符串值,然后使用 react-json-schema 来获取组件.这似乎太复杂了,所以我希望有一种方法可以在 DefinePlugin 中定义方法.

Google search comes up nill. My next step would be to pass a string value and then use react-json-schema to pick up the component. That seems too involved, so I'm hoping there's a way to define methods in DefinePlugin.

编辑为了澄清起见,我正在做的是构建一个可以注册到私有 npm 注册表的通用 redux 模块.调用时,可以为该模块提供 API url 和响应翻译器的覆盖.这可以防止我每次为不同的供应商安装时分支代码或创建 99% 相似的模块.

EDIT For clarification, what I'm doing is build a generic redux module which can registered to a private npm registry. When invoked, this module can be supplied overrides for the API urls and response translators. This prevents me from branching code or creating modules that are 99% similar every time I do an install for a different vendor.

如果通过环境变量提供函数是不合适的,那么允许这种覆盖的替代方法是什么?我不确定配置对象在通过商店分派时是否会起作用.我正在使用的另一个选项是覆盖模块中的整个文件.我熟悉 Ruby 中使用 import_path 的方法,但在研究中,我还没有看到任何等效的 JS/npm 方法.

If supplying functions through an environment variable is not appropriate, what would be an alternative method to allow for such overrides? I'm not sure the config object plays out when things are being dispatched through the store. The other option I'm playing around with is overriding entire files in a module. I'm familiar methods in Ruby using import_path, but in research, I haven't seen any equivalent JS/npm methods.

推荐答案

DefinePlugin 是一种直接的文本替换,类似于 C 中的宏.Webpack 将查找标识符并将其替换为给定的细绳.以下示例说明了其工作原理.

The DefinePlugin is a direct text replacement, similar to macros in C. Webpack will look for the identifier and replace it with the given string. The following example illustrates how that works.

使用以下插件配置

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 作为输入:

and the JavaScript as input:

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 将是:

The output JavaScript will be:

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 中定义的值.如果您运行它,您将获得以下控制台日志:

As you can see they have simply been replaced with the values defined in the DefinePlugin. If you run it you'll get the following console log:

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 还显示它会在任何地方被替换,它不是引用相同的函数,因为它是直接文本替换.

For STRING you would usually use JSON.stringify(), which just gives you a string representation of the string (quotes inside quotes). If you don't do that, it will simply be an identifier, and if the identifier wasn't defined, it will throw an error. The FUNCTION also shows that it will be replaced everywhere, it's not referencing the same function, because it's a direct text replacement.

如果你想选择性地定义一些东西,你还需要检查变量是否存在,因为如果不存在,它会抛出一个错误.

If you want to optionally define something you also need to check whether the variable exists, because if you don't, it will throw an error.

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

你不能做 VAR === undefined 因为它假设变量存在并且只会检查它是否未定义,但是当它根本没有定义时,它会抛出一个错误 VAR 未定义.之后,您可以自由地使用该变量并按照您的需要使用它并检查它是否是一个函数(在检查一个函数时,您可以跳过它是否已定义的测试,因为这将使用 typeof无论如何).

You can't do VAR === undefined because that assumes the variable exists and will only check whether it's undefined, but when it's not defined at all, it will throw an error that VAR is not defined. After that you can freely use the variable and use it like you wanted and check whether it's a function or not (when checking for a function you could skip the test whether it has been defined, because that would use a typeof anyway).

老实说,这不是一个很好的解决方案,特别是因为一个函数将被包含两次,因为需要 typeof 检查.公平地说,这种文本替换不适用于任何有条件定义的动态结构.将它移动到配置对象会是一个更好的主意.接受配置对象并提供默认值非常简单.有几种方法可以做到这一点.

To be honest, that's not a very good solution, especially since a function will be included twice, because of the needed typeof check. And to be fair, such text replacement is not appropriate for any conditionally defined dynamic structure. It would be a much better idea to move this to a configuration object. It's very straightforward to accept a configuration object and provide default values. There are several ways to accomplish that.

例如 Object.assign:

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

  // Use the options later
}

这篇关于webpack - 定义插件方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆