webpack v2 中全局的 promise polyfill 是如何实现的?
How is the global promise polyfill implemented in webpack v2?
我想更好地理解 webpack 中 promise 实现方式的区别。通常,幸福的无知足以让我主要开发应用程序,但我肯定对如何正确开发 plugin/tool/lib.
有点困惑
在创建应用程序时,以下两种方法从未引起任何问题;我想主要是因为没关系
webpack.config.js - 使用 babel-polyfill 作为入口点
module.exports = {
entry: {
foo: [
'core-js/fn/promise', <-- here
'./js/index.js'
]
},
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader'
}
]
}
}
Q: In this approach, since it's a polyfill it modifies the global Promise?
webpack 配置 - 使用 webpacks 提供的 shimming 插件
module.exports = {
entry: './js/index.js',
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader'
}
]
},
plugins: [
new webpack.ProvidePlugin({
Promise: 'es6-promise' <-- here
})
]
};
Q: Does this mean that the Promise is a module only specific to the webpack bundling process? Does the transpiled ES5 code have a local copy or es6-promise? Does it patch the global Promise?
关于创建一个使用 babel 进行转译的 jquery plugin/tool/lib...
webpack.config.js - 使用 babel-plugin-transform-runtime
module.exports = {
entry: {
foo: [
'./js/start.js'
]
},
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader'
}
]
}
}
.babelrc
{
"presets": [ "es2015" ],
"plugins": ["transform-runtime"] <--here
}
start.js
require('babel-runtime/core-js/promise').default = require('es6-promise'); <--here
require('plugin');
Q: This aliases the es6-promise to the babel-runtime promise and is not global but only local to the tool?
webpack 条目中的 Polyfill
entry: ['core-js/fn/promise', './index.js']
这与在入口点顶部导入它的效果相同。
In this approach, since it's a polyfill it modifies the global Promise?
是的,这个 polyfill 改变了全局 Promise
。称它为 polyfill 通常意味着它修补了全局内置插件,尽管这并没有严格遵守。如果他们不改变现有的 API 而只是提供功能,他们有时被称为 Ponyfills.
Webpack 使用 ProvidePlugin
new webpack.ProvidePlugin({
Promise: 'es6-promise'
})
ProvidePlugin
will import the configured module at the beginning of the module that uses it when the corresponding free variable is found. A free variable 是一个尚未在当前范围内声明的标识符。全局变量是所有局部范围内的自由变量。
每当遇到空闲 Promise
时,webpack 都会将以下内容添加到模块的开头:
var Promise = require('es6-promise');
Does this mean that the Promise is a module only specific to the webpack bundling process?
这是正确的,因为 ProvidePlugin
是特定于 webpack 的,任何其他工具都不太可能遵守任何 webpack 设置。
Does the transpiled ES5 code have a local copy or es6-promise?
与任何其他模块一样,它被 webpack 包含一次,所有导入都引用该模块。
Does it patch the global Promise?
它只会修改全局 Promise
如果导入的模块明确地这样做。您正在使用的 es6-promise
默认情况下不会修补全局,如 Auto-polyfill.
所示
Babel 变换运行时间
{
"plugins": ["transform-runtime"]
}
babel-plugin-transform-runtime
使用 core-js
来提供缺少的功能,例如 Promise
。你会记得,我说过 core-js
修改全局 Promise
。对于这种情况,情况并非如此,因为 babel 使用不污染全局命名空间的版本,如 core-js
README 中所述,它位于 core-js/library
中。例如:
const Promise = require('core-js/library/fn/promise');
Babel 将导入 core-js
Promise 并将 Promise
替换为导入的变量。另请参阅 babel-plugin-transform-runtime
- core-js
aliasing 中的示例。这与 webpack 的 ProvidePlugin
本质上是一样的,除了 babel 不捆绑模块,所以它只是添加导入。
This aliases the es6-promise to the babel-runtime promise and is not global but only local to the tool?
它不是全局的,因为它只是一个模块。 Babel 获取你的 JavaScript 并输出一些其他的 JavaScript ,其中配置的功能被转换为 ES5。您将 运行 或捆绑生成的 JavaScript 并且它实际上与您首先编写 ES5 相同。
require('babel-runtime/core-js/promise').default = require('es6-promise');
修改导出后,模块将使用 es6-promise
。但是覆盖导出不是一个好主意,特别是因为 ES 模块的导入在规范中是不可变的。 Babel 目前在这方面不符合规范。有关详细信息,请参阅 Making transpiled ES modules more spec-compliant。
你应该使用哪一个?
这取决于你在做什么。除了他们是否改变全局变量的不同之外,你可以选择你喜欢的任何一个。例如使用 babel 的 transform 运行time 允许你将它与任何使用 babel 的工具一起使用,而不仅仅是 webpack。
图书馆
None.
将 polyfill 留给应用程序开发人员。但是你可能会提到它依赖于某个特性,当用户想要在不支持该特性的环境中使用该库时,他们必须对其进行 polyfill。假设 Promises 得到广泛支持也是相当合理的,如果应用程序针对较旧的环境,它们很可能已经对其进行了 polyfill。请记住,这并不意味着您不应该转换新功能/语法。这专门用于 Promise
或 String.prototype.trimLeft
.
等新功能
对于工具
这也取决于您对工具的定义。假设工具是开发人员使用的一款软件(例如 webpack、eslint 等)。在那种情况下,它与任何应用程序完全相同,归根结底,它只是另一个应用程序,但仅针对开发人员。具体说到命令行工具,您应该决定要支持的最低 Node 版本并包括为此所需的任何内容,您可以在 engines
field.[=54= 中的 package.json
中指定]
对于插件
插件是一个非常宽泛的术语,可以是介于库和应用程序之间的任何东西。例如,webpack 插件或加载器应该按原样工作,而 jQuery 插件将成为网络应用程序的一部分,您应该将其视为库(它们可能应该称为库而不是插件)。通常,无论您要扩展什么,您都希望符合准则。看看它,看看他们的目标是什么。例如 webpack 目前支持 Node verions >=4.3.0,所以你的插件也应该支持。
我想更好地理解 webpack 中 promise 实现方式的区别。通常,幸福的无知足以让我主要开发应用程序,但我肯定对如何正确开发 plugin/tool/lib.
有点困惑在创建应用程序时,以下两种方法从未引起任何问题;我想主要是因为没关系
webpack.config.js - 使用 babel-polyfill 作为入口点
module.exports = {
entry: {
foo: [
'core-js/fn/promise', <-- here
'./js/index.js'
]
},
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader'
}
]
}
}
Q: In this approach, since it's a polyfill it modifies the global Promise?
webpack 配置 - 使用 webpacks 提供的 shimming 插件
module.exports = {
entry: './js/index.js',
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader'
}
]
},
plugins: [
new webpack.ProvidePlugin({
Promise: 'es6-promise' <-- here
})
]
};
Q: Does this mean that the Promise is a module only specific to the webpack bundling process? Does the transpiled ES5 code have a local copy or es6-promise? Does it patch the global Promise?
关于创建一个使用 babel 进行转译的 jquery plugin/tool/lib...
webpack.config.js - 使用 babel-plugin-transform-runtime
module.exports = {
entry: {
foo: [
'./js/start.js'
]
},
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader'
}
]
}
}
.babelrc
{
"presets": [ "es2015" ],
"plugins": ["transform-runtime"] <--here
}
start.js
require('babel-runtime/core-js/promise').default = require('es6-promise'); <--here
require('plugin');
Q: This aliases the es6-promise to the babel-runtime promise and is not global but only local to the tool?
webpack 条目中的 Polyfill
entry: ['core-js/fn/promise', './index.js']
这与在入口点顶部导入它的效果相同。
In this approach, since it's a polyfill it modifies the global Promise?
是的,这个 polyfill 改变了全局 Promise
。称它为 polyfill 通常意味着它修补了全局内置插件,尽管这并没有严格遵守。如果他们不改变现有的 API 而只是提供功能,他们有时被称为 Ponyfills.
Webpack 使用 ProvidePlugin
new webpack.ProvidePlugin({
Promise: 'es6-promise'
})
ProvidePlugin
will import the configured module at the beginning of the module that uses it when the corresponding free variable is found. A free variable 是一个尚未在当前范围内声明的标识符。全局变量是所有局部范围内的自由变量。
每当遇到空闲 Promise
时,webpack 都会将以下内容添加到模块的开头:
var Promise = require('es6-promise');
Does this mean that the Promise is a module only specific to the webpack bundling process?
这是正确的,因为 ProvidePlugin
是特定于 webpack 的,任何其他工具都不太可能遵守任何 webpack 设置。
Does the transpiled ES5 code have a local copy or es6-promise?
与任何其他模块一样,它被 webpack 包含一次,所有导入都引用该模块。
Does it patch the global Promise?
它只会修改全局 Promise
如果导入的模块明确地这样做。您正在使用的 es6-promise
默认情况下不会修补全局,如 Auto-polyfill.
Babel 变换运行时间
{
"plugins": ["transform-runtime"]
}
babel-plugin-transform-runtime
使用 core-js
来提供缺少的功能,例如 Promise
。你会记得,我说过 core-js
修改全局 Promise
。对于这种情况,情况并非如此,因为 babel 使用不污染全局命名空间的版本,如 core-js
README 中所述,它位于 core-js/library
中。例如:
const Promise = require('core-js/library/fn/promise');
Babel 将导入 core-js
Promise 并将 Promise
替换为导入的变量。另请参阅 babel-plugin-transform-runtime
- core-js
aliasing 中的示例。这与 webpack 的 ProvidePlugin
本质上是一样的,除了 babel 不捆绑模块,所以它只是添加导入。
This aliases the es6-promise to the babel-runtime promise and is not global but only local to the tool?
它不是全局的,因为它只是一个模块。 Babel 获取你的 JavaScript 并输出一些其他的 JavaScript ,其中配置的功能被转换为 ES5。您将 运行 或捆绑生成的 JavaScript 并且它实际上与您首先编写 ES5 相同。
require('babel-runtime/core-js/promise').default = require('es6-promise');
修改导出后,模块将使用 es6-promise
。但是覆盖导出不是一个好主意,特别是因为 ES 模块的导入在规范中是不可变的。 Babel 目前在这方面不符合规范。有关详细信息,请参阅 Making transpiled ES modules more spec-compliant。
你应该使用哪一个?
这取决于你在做什么。除了他们是否改变全局变量的不同之外,你可以选择你喜欢的任何一个。例如使用 babel 的 transform 运行time 允许你将它与任何使用 babel 的工具一起使用,而不仅仅是 webpack。
图书馆
None.
将 polyfill 留给应用程序开发人员。但是你可能会提到它依赖于某个特性,当用户想要在不支持该特性的环境中使用该库时,他们必须对其进行 polyfill。假设 Promises 得到广泛支持也是相当合理的,如果应用程序针对较旧的环境,它们很可能已经对其进行了 polyfill。请记住,这并不意味着您不应该转换新功能/语法。这专门用于 Promise
或 String.prototype.trimLeft
.
对于工具
这也取决于您对工具的定义。假设工具是开发人员使用的一款软件(例如 webpack、eslint 等)。在那种情况下,它与任何应用程序完全相同,归根结底,它只是另一个应用程序,但仅针对开发人员。具体说到命令行工具,您应该决定要支持的最低 Node 版本并包括为此所需的任何内容,您可以在 engines
field.[=54= 中的 package.json
中指定]
对于插件
插件是一个非常宽泛的术语,可以是介于库和应用程序之间的任何东西。例如,webpack 插件或加载器应该按原样工作,而 jQuery 插件将成为网络应用程序的一部分,您应该将其视为库(它们可能应该称为库而不是插件)。通常,无论您要扩展什么,您都希望符合准则。看看它,看看他们的目标是什么。例如 webpack 目前支持 Node verions >=4.3.0,所以你的插件也应该支持。