如何在webpack v2中实现全局承诺polyfill?

Jef*_*eff 4 javascript polyfills webpack babeljs

我想更好地理解在webpack中如何实现promise的区别.通常情况下,由于我主要开发应用程序,幸福的无知已经足够了,但我肯定对如何正确开发插件/工具/库有点困惑.


在创建应用程序时,以下两种方法从未引起任何问题; 我想主要是因为没关系

webpack.config.js - 使用babel-polyfill作为入口点

module.exports = {
  entry: {
    foo: [
      'core-js/fn/promise',          <-- here
      './js/index.js'
    ]
  },

  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'babel-loader'
      }
    ]
  }
}
Run Code Online (Sandbox Code Playgroud)

问:在这种方法中,因为它是一个polyfill,它修改了全局Promise?

webpack config - 使用webpacks填充提供插件

module.exports = {
  entry: './js/index.js',

  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'babel-loader'
      }
    ]
  },

  plugins: [
    new webpack.ProvidePlugin({
      Promise: 'es6-promise'          <-- here
    })
  ]
};
Run Code Online (Sandbox Code Playgroud)

问:这是否意味着Promise是一个仅针对webpack捆绑流程的模块?已转换的ES5代码是否具有本地副本或es6-promise?它会修补全球承诺吗?


关于创建一个jquery插件/工具/ lib,它使用babel进行转换...

webpack.config.js - 使用babel-plugin-transform-runtime

module.exports = {
  entry: {
    foo: [
      './js/start.js'
    ]
  },

  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'babel-loader'
      }
    ]
  }
}
Run Code Online (Sandbox Code Playgroud)

.babelrc

{
  "presets": [ "es2015" ],
  "plugins": ["transform-runtime"]     <--here
}
Run Code Online (Sandbox Code Playgroud)

start.js

require('babel-runtime/core-js/promise').default = require('es6-promise');  <--here
require('plugin');
Run Code Online (Sandbox Code Playgroud)

问:这将使es6-promise与babel-runtime承诺混淆,并且不是全局的,而只是该工具的本地版本?

Mic*_*ngo 10

在webpack条目中填充

entry: ['core-js/fn/promise', './index.js']
Run Code Online (Sandbox Code Playgroud)

这与您在入口点顶部导入它的效果相同.

在这种方法中,因为它是一个polyfill,它修改了全局Promise?

是的,这个polyfill改变了全局Promise.将其称为polyfill通常意味着它会修补全局内置函数,尽管这并未严格遵守.如果他们不更改现有API但仅提供功能,则有时称为Ponyfills.

Webpack填充 ProvidePlugin

new webpack.ProvidePlugin({
  Promise: 'es6-promise'
})
Run Code Online (Sandbox Code Playgroud)

ProvidePlugin将在使用它时,相应的模块的开头导入配置的模块自由变量被发现.甲自由变量是未在当前范围内被声明的标识符.全局变量是所有本地范围中的自由变量.

每当Promise遇到free 时,webpack会将以下内容添加到模块的开头:

var Promise = require('es6-promise');
Run Code Online (Sandbox Code Playgroud)

这是否意味着Promise是一个仅适用于webpack捆绑过程的模块?

这是正确的,因为ProvidePlugin特定于webpack,并且任何其他工具都不太可能尊重任何webpack设置.

已转换的ES5代码是否具有本地副本或es6-promise?

与任何其他模块一样,它由webpack包含一次,所有导入都引用该模块.

它会修补全球承诺吗?

Promise如果导入的模块明确地执行它,它将仅修改全局.在es6-promise你使用,如在默认情况下没有打补丁的全球自动填充工具.

Babel变换运行时

{
  "plugins": ["transform-runtime"]
}
Run Code Online (Sandbox Code Playgroud)

用于提供缺失功能的babel-plugin-transform-runtime用途.你会记得,我说过修改了全局.对于这种情况,情况并非如此,因为babel使用的版本不会污染全局命名空间,如README中所述.例如:core-jsPromisecore-jsPromisecore-js/librarycore-js

const Promise = require('core-js/library/fn/promise');
Run Code Online (Sandbox Code Playgroud)

Babel将导入core-jsPromise并替换Promise为导入的变量.另请参阅babel-plugin-transform-runtime- core-js别名中的示例.这与webpack的基本相同,ProvidePlugin只是babel没有捆绑模块,所以它只是添加导入.

这将es6-promise别名为babel-runtime承诺,并不是全局的,而只是工具的本地?

它不是全球性的,因为它只是一个模块.Babel接受您的JavaScript并输出一些其他JavaScript,其中配置的功能被转换为ES5.您将运行或捆绑生成的JavaScript,它几乎与您首先编写ES5一样.

require('babel-runtime/core-js/promise').default = require('es6-promise');
Run Code Online (Sandbox Code Playgroud)

有了它你修改导出,因此模块将使用es6-promise.但是覆盖导出并不是一个好主意,特别是因为ES模块的导入在规范中是不可变的.Babel目前在这方面不符合规范.有关更多详细信息,请参阅使已编译的ES模块更符合规范.


你应该使用哪一个?

这取决于你在做什么.除了他们是否改变全局变量的区别,你可以选择你喜欢的.例如,使用babel的变换运行时允许您将它与任何使用babel的工具一起使用,而不仅仅是使用webpack.

对于图书馆

没有.

将polyfill留给应用程序开发人员.但您可能会提到它取决于某个功能,当用户想要在不支持该功能的环境中使用该库时,他们必须对其进行填充.假设Promises得到广泛支持并且如果应用程序针对较旧的环境,它们很可能已经将其填充了,这也是相当合理的.请记住,这并不意味着您不应该转换新的功能/语法.这专门针对像Promise或等新功能String.prototype.trimLeft.

对于一个工具

这还取决于您对工具的定义.让我们假设一个工具是开发人员使用的一个软件(例如webpack,eslint等).在这种情况下,它与任何应用程序完全相同,在一天结束时,它只是另一个应用程序,但仅针对开发人员.特别是关于命令行工具,您应该决定要支持的最小节点版本,并包含所需的任何内容,您可以package.jsonengines字段中指定.

对于插件

插件是一个非常广泛的术语,可以是库和应用程序之间的任何东西.例如,webpack插件或加载器应该按原样工作,而jQuery插件将成为Web应用程序的一部分,您应该将其视为库(它们应该被称为库而不是插件).通常,您希望符合您所扩展的指南.看看它,看看它们的目标是什么.例如,webpack目前支持节点版本> = 4.3.0,因此您的插件也应如此.

  • 我真的不能表达我对这篇文章的感激之情; 感谢您抽出宝贵时间撰写如此简洁的答案.这个单一的帖子胜过了我整个工作日的总体研究,哈哈... (2认同)