babel-polyfill在Babel7以后名字是@babel/polyfill。在引入polyfill一节,我们学习了polyfill的入门知识,在本节将会深入讲解。
本节配套代码是github仓库 https://github.com/jruit/babel-tutorial 的babel03-babel08例子
polyfill广义上讲是为环境提供不支持的特性的一类文件或库,既有Babel官方的库,也有第三方的。babel-polyfill指的是Babel官方的polyfill,本教程默认使用babel-polyfill。polyfill传统上分两类,一类是已构建成JS文件的polyfill.js,另一类是未构建的需要安装npm包@babel/polyfill。因为@babel/polyfill本质是由两个npm包core-js与regenerator-runtime组合而成的,所以在使用层面上还可以再细分为是引入@babel/polyfill本身还是其组合子包。
总体来说,Babel官方的polyfill使用方法主要有如下几种:
- 直接在html文件引入Babel官方的polyfill.js脚本文件;
- 在前端工程的入口文件里引入polyfill.js;
- 在前端工程的入口文件里引入@babel/polyfill;
- 在前端工程的入口文件里引入core-js/stable与regenerator-runtime/runtime;
- 在前端工程构建工具的配置文件入口项引入polyfill.js;
- 在前端工程构建工具的配置文件入口项引入@babel/polyfill;
- 在前端工程构建工具的配置文件入口项引入core-js/stable与regenerator-runtime/runtime;
所有的例子,我们仍以火狐27.0不支持的Promise为例,进行演示。该版本的火狐,在遇到如下代码的时会报错
var promise = Promise.resolve('ok'); console.log(promise);
报错信息为:ReferenceError: Promise is not defined
我们需要做的就是让火狐27.0可以正常运行我们的代码,下面对上文提到的7种方法进行讲解。
1. 直接在html文件引入Babel官方的polyfill.js脚本文件
该方法在分类上属于使用已构建成JS文件polyfill.js的一类,该方法在引入polyfill一节已经讲过,本节不再重复讲解。
2. 在前端工程的入口文件里引入polyfill.js
github配套的代码是babel03例子
该方法在分类上属于使用已构建成JS文件polyfill.js的一类,该我们以目前业界最为流行的webpack打包工具为例,讲述该方法。
我们的工程里有a.js与index.html文件,a.js文件的内容是
var promise = Promise.resolve('ok'); console.log(promise);
index.html文件在head标签里直接引入了a.js文件,这个时候在火狐27.0下打开该html会报错。
在之前的例子里,我们是在index.html里单独引入了polyfill.js文件对API进行补齐。现在,我们换一种方式,通过在工程入口文件a.js引入polyfill.js进行补齐。
我们使用webpack来讲述这个过程,首先进行webpack和其命令行工具的安装
npm install webpack webpack-cli --save-dev
在webpack4.0和node8.2以上版本,我们可以使用npx webpack a.js -o b.js命令来进行打包。该命令的意思是,指定工程入口文件是a.js,最后打包成b.js。
为了方便,我们在package.json里配置scripts项,现在,只需要执行npm run dev,就会自动执行npx webpack a.js -o b.js命令,即可完成打包。
"scripts": { "dev": "npx webpack a.js -o b.js" },
在我们这个例子里,前端工程入口文件是a.js,我们只需要在a.js最上方加入一句
import './polyfill.js';
然后执行npm run dev,就可以把polyfill打包到我们的最终生成的文件里(我们需要提前在相应的文件目录里存放polyfill.js)。
现在,我们把index.html使用的a.js改成b.js,然后在火狐27.0打开,可以看到控制台已经正常。
3. 在前端工程的入口文件里引入@babel/polyfill
配套代码是babel04例子。
该方法在分类上属于使用未构建的需要安装npm包@babel/polyfill的一类,其实整个过程和上面的例子非常像,不一样的地方如下。
1) a.js里的
import './polyfill.js';
改成
import '@babel/polyfill';
2)删除工程目录下的polyfill.js文件,同时安装@babel/polyfill这个npm包
npm install --save @babel/polyfill
除了这两点,其余的地方和上面的例子完全。
执行npm run dev,然后和之前一样在火狐打开进行验证正常。
4. 在前端工程的入口文件里引入core-js/stable与regenerator-runtime/runtime
配套代码是babel05例子。
该方法在分类上属于使用未构建的需要安装npm包@babel/polyfill的组合子包的一类,我们仍以目前业界最为流行的webpack构建工具为例,讲述该方法。后续默认是使用webpack。
该方法需要我们单独安装单独安装core-js与regenerator-runtime这两个npm包,这种方式core-js是默认是3.x.x版本。
需要注意的是,我们使用该方法的时候,不能再安装@babel/polyfill了。因为@babel/polyfill在安装的时候,会自动把core-js与regenerator-runtime这两个依赖安装上了,而@babel/polyfill使用的core-js已经锁死为2.x.x版本了。core-js的2.x.x版本里并没有stable文件目录,所以安装@babel/polyfill后再引入core-js/stable会报错。
其实这个方法和上面的例子也是非常像,就是把一个npm包换成了两个而已。不一样的地方具体如下
1) a.js里的
import '@babel/polyfill';
改成
import "core-js/stable"; import "regenerator-runtime/runtime";
2)安装两个npm包core-js和regenerator-runtime
npm install --save core-js regenerator-runtime
替换之前安装的@babel/polyfill
执行npm run dev,然后和之前一样在火狐打开进行验证正常。
5. 在前端工程构建工具的配置文件入口项引入polyfill.js
配套代码是babel06例子。
webpack的配置文件有多种类型,我们采用webpack.config.js,其它类型的webpack配置文件与其一致。
因为要在webpack配置文件里指定入口文件,我们就不手动使用webpack a.js -o b.js来进行打包了,而是在webpack.config.js进行设置。
const path = require('path'); module.exports = { entry: ['./a.js'], output: { filename: 'b.js', path: path.resolve(__dirname, '') }, mode: 'development' };
webpack的配置文件的入口项是entry,这里entry的值我们设置成数组,a.js就是入口文件。然后,package.json里的dev命令改为
"scripts": { "dev": "npx webpack" },
现在我们执行npm run dev,webpack就完成了打包。现在我们index.html直接引用b.js,火狐27会报错。原因我们都知道,我们没有使用polyfill。
那么,在前端工程构建工具的配置文件入口项引入polyfill.js,该怎么操作呢?
其实很简单,那就是把数组的第一项改成'./polyfill.js',原先的入口文件作为数组的第二项,polyfill就会打包到我们生成后的文件里了。
const path = require('path'); module.exports = { entry: ['./polyfill.js', './a.js'], output: { filename: 'b.js', path: path.resolve(__dirname, '') }, mode: 'development' };
现在再执行npm run dev进行打包,然后index.html就不会在火狐27里报错了。
6. 在前端工程构建工具的配置文件入口里引入@babel/polyfill;
配套代码是github上的babel07例子。
如果你对之前讲的方法都理解的话,那么相信你也会很容易理解该方法。该方法就是把上个方法的entry的第一项换成@babel/polyfill,并且安装了@babel/polyfill这个包就可以了。
npm install --save @babel/polyfill
webpack.config.js配置如下
const path = require('path'); module.exports = { entry: ['@babel/polyfill', './a.js'], output: { filename: 'b.js', path: path.resolve(__dirname, '') }, mode: 'development' };
现在再执行npm run dev进行打包,然后index.html就不会在火狐27里报错了。
7. 在前端工程构建工具的配置文件入口里引入core-js/stable与regenerator-runtime/runtime
配套代码是github上的babel08例子。
其实这个方法和上面的例子也是非常像,就是把一个npm包换成了两个而已。我们需要做的就是安装两个npm包
npm install --save core-js regenerator-runtime
然后webpack.config.js的entry项数组的前两项改为core-js/stable和regenerator-runtime/runtime。
const path = require('path'); module.exports = { entry: ['core-js/stable', 'regenerator-runtime/runtime', './a.js'], output: { filename: 'b.js', path: path.resolve(__dirname, '') }, mode: 'development' };
现在再执行npm run dev进行打包,然后index.html就可以正常在火狐27.0运行了。
从babel7.4开始,官方不推荐再使用@babel/polyfill了,因为@babel/polyfill本身其实就是两个npm包的集合:core-js与regenerator-runtime。
官方推荐直接使用这两个npm包。虽然@babel/polyfill还在进行版本升级,但其使用的core-js包为2.x.x版本,而core-js这个包本身已经发布到了3.x.x版本了,@babel/polyfill以后也不会使用3.x.x版本的包了。新版本的core-js实现了许多新的功能,例如数组的includes方法。
虽然从babel7.4开始,不推荐再使用@babel/polyfill了,但我们仍然把传统@babel/polyfill的使用方式在本节进行讲解,这对于理解其使用方式是非常有帮助的。
ES6补齐API的方式,除了上述几种在前端工程入口文件或构建工具的配置文件里使用polyfill(或是其子包)的方式,还有使用Babel预设或插件进行补齐API的方式。
上述使用polyfill的方式,是把整个npm包或polyfill.js放到了我们最终的项目里了。完整的polyfill文件非常大,会影响我们的页面加载时间。
如果我们的运行环境已经实现了部分ES6的功能,那实在没有必要把整个polyfill都给引入。我们可以部分引入,这个时候需要使用Babel预设或插件了。
Babel预设或插件不光可以进行补齐API,还可以对API进行转换,这些使用方法在后面两节讲解。
小结
1.本节对使用polyfill进行了详细的梳理与讲解,把每一种使用方法都进行了讲述,并配有代码以便大家理解。
2.这么多的方法,在实际开发中该选择哪一种呢?从babel7.4版本开始,Babel官方已经不推荐再使用@babel/polyfill,这也包括官方的polyfill.js库文件。因此从2019年年中开始,我们的新项目都应该使用core-js和regenerator-runtime这两个包。即,我们应选择方法4与方法7。这两种方法,都是把两个npm包全部都引入到了我们的前端打包后的文件里了,对于部分引入的方法,我们将在后面两节进行讲解。
注
1.polyfill这个名词,现在有多种含义。可以是指polyfill.js,也可以是babel-polyfill,也可以是@babel/polyfill,也可以是core-js和regenerator-runtime等等。我们应该根据语境来理解其具体指代。总体来说,提到polyfill这个词,一般就是指我们开发过程需要对环境的缺失API特性提供支持。
babel-polyfill在Babel7以后名子是@babel/polyfill。
这里有个错别字,名子->名字,谢谢作者的付出!
感谢,已改正
良心啊好人有好报,不关注对不起自己
受教了,插件的历史变更竟能讲的如此清楚,真的是用心在写文章啊,受教了,可以像廖老师那样贴一张收款码,精美的文章就像良心的开源产品一样,创作不易,值得支持
哈哈哈,感谢 那我就放一个吧
作者的文章很用心 我每篇都认真看了 这里反馈个错别字(本来我认为错别在所难免的 在使用输入法时常常出现 但上面有人指明了 所以我也就指出来 希望作者的文章越来越好)
小结中 “2019年年中开始”后面 我就的-->我觉得
哈哈哈,感谢
意外发现的这个宝藏网站,真的真的太赞了,每篇文章都想非常赞,感觉就是站在小白我的角度在答疑解惑,太感谢了,大牛很多,能讲的这么详细且易懂的大牛很少👍
真的写的挺棒的,👍
疑问,文中说:“从babel7.4开始,官方不推荐再使用@babel/polyfill了”。问,babel 的版本 具体指的是哪个包?babel 一般大家安装的三剑客就是:@babel/cli、@babel/core、@babel/preset-env。说的 v7.4 是指哪个版本,有点懵。希望博主给解释一下。
有讲过这个的
@babel/core,但是,babel没有7.4,后面是8了
太感谢了,这一节竟然还学习到了一个关于webpack的知识点。
entry属性如果是一个字符串数组,那么还依旧属于是`单入口打包`,这样的目的是没必要在代码里显式地引入polyfill了,webpack会帮助打包且打包后的代码里,polyfill放置到最上面,方便了很多。
感谢博主,非常通俗易懂
想问下,哪里关注官方babel推荐用什么的呢
这个火狐27.0.1 下载后,在mac M2 上安装完打开不能用,有朋友遇到类似问题吗?还有其他可以测试低版本的浏览器版本推荐吗?
谢谢答疑