如何安装babel-polyfill库?

146

我刚开始使用Babel将我的ES6 JavaScript代码编译成ES5。当我开始使用Promises时,它似乎无法正常工作。Babel网站通过polyfills支持Promises。

可惜的是,我尝试添加以下内容却没有成功:

require("babel/polyfill");
或者
import * as p from "babel/polyfill";

因此,当我启动我的应用程序时,会出现以下错误:

找不到模块“babel/polyfill”

我搜索了该模块,但似乎我在这里缺少一些基本的东西。我还尝试添加旧版本和好用的bluebird NPM,但看起来它没有起作用。

如何使用Babel的polyfills?


1
npm install _name_ - dandavis
1
注意:Babel现在有一个单独的NPM包:babel-polyfill - Stijn de Witt
1
@StijndeWitt,为了方便您,这里是完整的README.md文件的全文版本: - gurghet
1
@gurghet 是的,我同意他们本可以添加更多信息 :) 但你真正需要知道的只有 npm install --save babel-polyfillrequire('babel-polyfill) - Stijn de Witt
1
由于您正在使用ES6,因此您还可以使用import "babel-polyfill"。 - Love Hasija
7个回答

69

在babel v6中有一些变化。

根据文档:

polyfill将模拟完整的ES6环境。当使用babel-node时,将自动加载此polyfill。

安装:
$ npm install babel-polyfill

在Node / Browserify / Webpack中使用:
要包含polyfill,您需要在应用程序入口点的顶部引用它。
require("babel-polyfill");

在浏览器中使用:
babel-polyfill npm发行版的 dist / polyfill.js 文件中获取。这需要在所有已编译的Babel代码之前包含。您可以将其预先添加到已编译的代码中,也可以在其前面包含<script>中。

注意:不要使用browserify等来require它,使用babel-polyfill


6
我仍不完全确定何时需要Polyfill。为什么ES6模块只需使用babel.js即可工作,但Array.prototype.findIndex()在没有Polyfill的情况下无法工作,而且当Babel编译代码时也不会引发异常?这就是Polyfill™的本质吗? - RemEmber
5
基本上,Babel polyfill 只是将 https://github.com/facebook/regenerator 和 https://github.com/zloirock/core-js 结合在一起。查看这两个仓库以确定你是否需要这些polyfill。 - vdclouis
7
我认为一个能正常工作而另一个不能的原因是,当Babel进行转译时,其针对一个假想的JS引擎进行编译,该引擎具有一定水平的支持。实际上,真实的浏览器可能支持的功能比这个假想的引擎多或少。实际上,我认为他们针对的假想浏览器在IE10级别左右,因此旧版本的浏览器可能会存在一些问题。通过将这些修复程序放入单独的polyfill中,他们将是否要支持这些旧版浏览器的决定留给了您,有点像jQuery的1.0分支支持IE8,而2.0分支则不支持IE8。@RemEmber - Stijn de Witt
2
如果findIndex是您唯一需要的polyfill,您可以在代码中的某个位置包含它。请查看MDN以获取polyfills:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex - vdclouis
1
@vdclouis,您会如何通过webpack将polyfill代码包含到项目中以便在整个项目中都可用? - dougmacklin
显示剩余2条评论

50

Babel文档简要地描述了这个:

Babel包含一个polyfill,其中包括自定义的regenerator runtime和core.js。

这将模拟完整的ES6环境。当使用babel-node和babel/register时,会自动加载此polyfill。

确保在应用程序的入口点之前要求它,在调用任何其它内容之前。如果你使用像webpack这样的工具,那就很简单(你可以告诉webpack将其包含在捆绑包中)。

如果你使用像gulp-babelbabel-loader这样的工具,则需要安装babel软件包本身以使用polyfill。

还要注意,对于影响全局范围(如polyfills)的模块,您可以使用简洁的导入来避免在您的模块中有未使用的变量:

import 'babel/polyfill';

4
补充一下,我不确定这完全正确,但我尝试仅使用 import 'babel-core/polyfill' 而没有安装 babel,结果运行良好。 - Nathan Lutterman
2
_Zaemz_,我猜你已经安装了babel,所以'import 'babel-core/polifyll''可以工作。我尝试过没有安装babel,对我来说无法运行。顺便提一下:_ssube_的建议是有效的。 - WebBrother
4
在使用webpack时,你应该将它包含在哪里? - theptrk
2
@theptrk 使用webpack,您可以将其作为模块简单导入,因为webpack允许导入npm包。对于Karma,您需要将其设置为文件,以便在测试之前包含它。 - ssube
3
谢谢,也许我使用的是不同版本,但我必须使用babel-core而不是"import 'babel-core/polyfill';" - theptrk
显示剩余2条评论

29

对于 Babel 7 版本,如果您正在使用 @babel/preset-env,在 babel 配置中添加一个名为'useBuiltIns'的标志,并将其值设置为'usage'即可包含所有 polyfill。无需在应用程序入口点要求或导入 polyfill。

使用此标志后,babel@7 将进行优化,并仅包括您需要的 polyfills。

安装完成后,使用此标志:

npm install --save-dev  @babel/core @babel/cli @babel/preset-env
npm install --save @babel/polyfill

只需添加标志:

useBuiltIns: "usage" 

将以下代码添加到名为“babel.config.js”的Babel配置文件中的“@babel/env”部分:

// file: babel.config.js

module.exports = () => {
   const presets = [
      [
         "@babel/env", 
         { 
             targets: { /* your targeted browser */ },
             useBuiltIns: "usage"  // <-----------------*** add this
         }
      ]
   ];

   return { presets };
};

参考资料:


2019年8月更新:

Babel 7.4.0(2019年3月19日发布)已将@babel/polyfill弃用。而安装core-js代替@babel/polyfill:

npm install --save core-js@3

您的 babel.config.js 中添加了一个新条目 corejs

// file: babel.config.js

module.exports = () => {
   const presets = [
      [
         "@babel/env", 
         { 
             targets: { /* your targeted browser */ },
             useBuiltIns: "usage",
             corejs: 3  // <----- specify version of corejs used
         }
      ]
   ];

   return { presets };
};

查看示例:https://github.com/ApolloTang/stackoverflow-eg--babel-v7.4.0-polyfill-w-core-v3

参考文献:


1
你在生产环境中使用这个吗?有任何风险吗? - Roy
useBuiltIns: "usage" 在我的程序中不起作用。它并没有在程序包中包含任何 polyfills(例如:我使用生成器时会出现错误 "regeneratorRuntime 未定义")。有什么建议吗? - WebBrother
@WebBrother,对我来说没问题... 请参见:https://github.com/ApolloTang/stackoverflow-eg--babel-polyfill - apollo
@Roy,我正在将一个企业项目从babel@6迁移到babel@7,以便我可以使用@babel/preset-typescript。这仍然是一个正在进行中的工作,但我正在遵循babel官方文档的指示(请参见我的答案中的参考链接)。到目前为止,一切似乎都在正常工作,但我还没有将我的迁移/升级工作发送给QA,如果出现任何问题,我会在这里发布。 - apollo
我仍然遇到这个错误 在浏览器中打开开发者工具... 找不到模块'metro/src/lib/polyfills/require.js' 要求堆栈: - Siddharth

19
如果你的 package.json 文件看起来像下面这样:
  ...
  "devDependencies": {
    "babel": "^6.5.2",
    "babel-eslint": "^6.0.4",
    "babel-polyfill": "^6.8.0",
    "babel-preset-es2015": "^6.6.0",
    "babelify": "^7.3.0",
  ...

如果你遇到了“找不到模块 'babel/polyfill'”的错误信息,那么你可能只需要更改你的导入语句。从以下语句更改:
import "babel/polyfill";

致:

import "babel-polyfill";

请确保它在任何其他import语句之前(不一定在应用程序的入口点)。

参考: https://babeljs.io/docs/usage/polyfill/


3
在这个答案中,“babel-polyfill”包被列在“devDependencies”下。这样做会导致在部署时不包括babel-polyfill。您不应该使用“-D”标志安装babel-polyfill,而是应该使用“-S”标志将其列在“dependencies”下,从而将其包括在您的部署中。 - apollo

9

首先,很明显的答案是没有人提供的,你需要将Babel安装到你的应用程序中:

npm install babel --save

(或者如果您想要require('babel-core/polyfill'),则为babel-core)。

除此之外,我有一个grunt任务将我的es6和jsx转译为构建步骤(即我不想使用babel/register,这就是为什么我首先尝试直接使用babel/polyfill的原因),所以我想更加强调@ssube答案中的这部分:

确保在应用程序的入口点之前,先引入它,然后再调用其他内容

我遇到了一些奇怪的问题,我尝试从某个共享环境启动文件中要求babel/polyfill,并且我得到了用户引用的错误 - 我认为这可能与babel如何排序导入与requires有关,但我现在无法复制。无论如何,在我的客户端和服务器启动脚本的第一行移动import 'babel/polyfill'可以解决这个问题。

请注意,如果您希望使用require('babel/polyfill'),我建议您确保所有其他模块加载器语句也是requires而不是使用imports - 避免混合两者。换句话说,如果您的启动脚本中有任何import语句,请将import babel/polyfill作为脚本中的第一行,而不是require('babel/polyfill')


10
不需要在使用npm时加上sudo命令。详见https://docs.npmjs.com/getting-started/fixing-npm-permissions。 - Vladimir Starkov

8

3

就像Babel在文档中所说,对于Babel > 7.4.0版本,模块@babel/polyfill已被弃用,因此建议直接使用以前包含在@babel/polyfill中的core-js和regenerator-runtime库

因此,以下内容适用于我:

npm install --save core-js@3.6.5
npm install regenerator-runtime

然后在你的初始JS文件的最顶部添加:

import 'core-js/stable';
import 'regenerator-runtime/runtime';

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接