babel6和babel7中关于polyfill和preset-env和babel-plugin-transform-runtime等总结

记录自己零散的收获,随笔。

一些基础

  1. babel的作用是转换JS新的特性代码为大部分浏览器能运行的代码。

  2. babel转码又分为两部分,一个是语法转换,一个是API转换。

  3. 对于API的转换又分为两部分,一个是全局API例如Promise,Set,Map还有静态方法Object.assign,另一个是实例方法例如Array.prototype.includes。对于实例方法core-js@2是转换不了的,只有core-js@3才会转换。

  4. babel代码转换依赖plugin,没有plugin的情况下babel做的事情只是 code => code

  5. plugin 有很多,一个个导入又特别麻烦,这时候我们又知道了preset。

preset是很多plugin的集合,配置如下:

.babelrc文件

{"presets": ["env"]
}

如果preset-env是有配置项的:

{"presets": [["env",{// 这里就是配置项}]]
}

可以观察出如果某个preset需要配置可以将字符串换成一个数组,第一项是preset的name,第二项就是options。plugin同preset。

注:preset是从右往左执行,plugin是从左往右执行,并且plugin先于preset执行。

babel6到babel7的升级是具有破坏性的,主要总结下polyfill的用法和在babel6和babel7中的不同。

babel-polyfill

上面说到babel主要做两件事,一个是转换语法,一个是兼容新的API。

babel-polyfill 的作用是兼容新的API。

babel7

babel7进行了较大的改动,废弃了 stage-x的preset,还增加了命名空间区分官方插件和非官方插件,@babel/core,@babel/cli等。

建议使用@babel/preset-env 。

@babel/plugin-transform-runtime

该插件的引入主要有两个作用

在babel7中,原先的插件babel-plugin-transform-runtime也做了修改 -> @babel/plugin-transform-runtime。并且在功能上也变强大了。

移除了polyfill的配置项添,加了corejs配置项。

@babel/plugin-transform-runtime的默认配合如下:

{plugins: [["@babel/plugin-transform-runtime", {"absoluteRuntime": false, // 不是很清除干啥的"corejs": false, // 下面详解"helpers": true, // 助手函数是否提取,同babel-plugin-transform"regenerator": true, // 同babel-plugin-transform"useESModules": false}]]
}

对于配置项 corejs: false | 2 | 3

false 依赖 @babel/runtime,是默认选项,认为需要填充的API以被填充,所以不对API作polyfill(对于@babel/runtime的依赖是提取的helper的依赖)。
2 依赖@babel/runtime-corejs2
3 依赖@babel/runtime-corejs3

corejs2和corejs3还是有很大区别的。corejs2只转换全局变量(Object)和静态方法(Object.assign),并不转换原型上的方法(Array.prototype.includes),corejs3会转换原型上的方法。

注意transform-runtime这个插件添加的polyfill都是私有的,不会影响到全局环境,而且还是按需引入,非常nice。

小结:
@babel/plugin-transform-runtime主要有三个作用:
- 当使用 generators/async的时候自动引入 @babel/runtime/regenerator
- 为新特性的API添加实现。
- 提取每个模块内联的helper们问引用。

@babel/preset-env

除了上面说的 @babel/plugin-transform-runtime插件,还想记录下 @babel/preset-env关于polyfill的改变。

这个preset在babel6的时候就承担了很多功能,本文只记录和polyfill相关的配置,useBuiltInscorejs

useBuiltIns

在babel-preset-env的配置项中是一个boolean值,在@babel/preset-env的时候则扩展了几个选项 "useage""entry"

默认值是false,表示不会自动引入polyfills,并且不会处理 import “@babel/polyfill” 和 import “corejs”。

注:babel7.4会放弃 @babel/polyfill,所以建议直接使用 corejs

entry

在入口文件有 import "core-js/stable"import "regenerator-runtime/runtime"
会被自动分割为各个模块的导入。

require("core-js/modules/es.symbol");require("core-js/modules/es.symbol.description");require("core-js/modules/es.symbol.async-iterator");require("core-js/modules/es.symbol.has-instance");...
...
...require("core-js/modules/web.url-search-params");require("regenerator-runtime/runtime");

只能在入口引入一次,多次会报错。

usage

按需引入。同样会造成全局污染。在我的理解中这个选项只是entry的一种增强,不需要在入口手动引入一次,并且可以按照使用特性多少按需引入。

corejs

值:2, 3 或者 { version: 2 | 3, proposals: boolean }, 默认是 2.

这是新加的一个配置项。该选项只会在 useBuiltIns选项为 usage或者 entry并且 @babel/preset-env正确导入对应的corejs版本的情况下起作用。

默认情况下只会注入稳定功能的 ECMAScript 特性。有三个特性可以修改:

  • 当时用配置 useBuiltIns: "entry"可以直接导入提案 import "core-js/proposals/string-replace-all"
  • 当时用 useBuiltIns: usage 的时候又有两个可选:
    • 将shippedProposals(@babel/preset-env的另一个配置项)选项设置为true。这将启用已在浏览器中提供一段时间的提议的polyfill和转换。
    • 使用 corejs: {version:3,proposal:true}。这样可以实现对core-js支持的每个提案的填充。

babel6

据我所知,在babel6中使用polyfill有四种方法:

  1. 直接引入(影响全局,一劳永逸)

    在入口文件中 import 'babel-polyfill' / require('babel-polyfill')。使用webpack的话也可以在entry中添加 entry: ['babel-polyfill', 'src/index.js']

    优点:
    一次引入,全局使用。
    会转换实例方法和静态方法,比较全面。

    缺点:
    影响全局作用域。
    打出来的包比较大,不管用没用到都打进去了。

    使用场景:
    开发业务项目,比较全面,不会漏了从而出问题,比如Object.assign这样的方法在ios8上面还是需要polyfill的。

  2. 在babel-runtime中单独引入

    和直接在入口引入polyfill不同,该插件引入的polyfill是模块私有的。
    对于需要的polyfill需要手动引入,import Promise from 'babel-runtime/core-js/promise'

    优点:
    该模块私有,不会影响到全局作用域。
    打出来的包因为按需引入包不会很大。

    缺点:
    因为不影响全局作用域,所以不会转实例和静态方法这样的API。
    手动引入所需,搞不好会漏掉。

    使用场景:
    开发库,框架之类可以使用,因为别人用你的东西然后不知情的情况下你改了别人的全局环境,然后出错了就尴尬了。

  3. 使用babel-plugin-transform-runtime按需引入

    这个插件可不简单,有好几个功能:

    1. 和插件babel-runtime一样引入的polyfill是私有的,不会影响全局作用域。并且是自动按需引入需要的polyfill,不需要想babel-runtime一样一个一个手动引入。
    2. 可以提取语法转换时候每个模块都生成的各种helper,成一个引用。
    3. 自动转换generators/async。

    优点:
    该模块私有,不会影响到全局作用域。
    打出来的包因为按需引入包不会很大。
    自动按需引入,不需要手动,防止遗漏。
    提取helper,大大减少冗余代码。

    缺点:
    因为不影响全局作用域,所以不会转实例和静态方法这样的API。

    使用场景:
    同babel-runtime。

    注:该插件依赖babel-runtime。

  4. 在babel-preset-env中设置配置项

{"presets": [["env", {"useBuiltIns": boolean}]]
}

useBuiltIns 选项是为了分割入口的 import 'babel-polyfill' / require(babel-polyfill)成按环境引入polyfill。该方式同第一中引入polyfill的方式,但是会按照配置的环境去按需引入,稍微好点。

小结:
1. babel6的核心有 babel-core babel-cli babel-node babel-register babel-polyfill,这些在babel7会有所修改。
2. polyfill 是依赖core-js的
3. babel7.4放弃了@babel/polyfill直接依赖core-js@2或者3。

babel-plugin-transform-runtime的配置项

{"helpers": false, // defaults to true"polyfill": false, // defaults to true"regenerator": true, // defaults to true"moduleName": "babel-runtime" // defaults to "babel-runtime"
}

对于polyfill的自动处理和helper的提取都是依赖babel-runtime完成的,所以该插件依赖babel-runtime。

polyfill例子

input:

var promise = new Promise;

output:

var _promise = require("babel-runtime/core-js/promise");  // 注意这里,根本是从core-js里面引入的var _promise2 = _interopRequireDefault(_promise);function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var promise = new _promise2.default();

helper的例子:

input:

class Person {}

usually turns into:

"use strict";// 这就是helper函数,每个模块都会被实现一遍,十分浪费,冗余。
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }var Person = function Person() {_classCallCheck(this, Person);
};

通过runtime转一下:

"use strict";var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); // 从runtime中引入,没有再实现一遍var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var Person = function Person() {(0, _classCallCheck3.default)(this, Person);
};

generator同样是 require("babel-runtime/regenerator");引入的。

参考

babel官网@babel/plugin-transform-runtime
npm->babel-plugin-transform-runtime
babel到底该如何配置?
babel手册
Babel是一个JavaScript编译器
babel7简单升级

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/362069.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

十六、CI框架之数据库操作get用法

一、使用数据库的Get方法读取内容,如下代码: 二、数据库如下: 二、效果如下: 转载于:https://www.cnblogs.com/tianpan2019/p/11141809.html

使用Spring Boot和Spring MVC自定义HttpMessageConverters

为Spring Boot应用程序或直接的Spring MVC应用程序公开基于REST的终结点很简单,以下是一个控制器,该终结点公开了一个终结点,用于基于其发布的内容创建实体: RestController RequestMapping("/rest/hotels") public cl…

JS如何禁止别人查看网站源码

四种查看路径: 查看效果:猛戳 1、直接按F12 2、Ctrl Shift I查看 3、鼠标点击右键查看 4、Ctrl uview-source: url 把以上三种状态都屏蔽掉就可以了,document有onkeydown(键盘按键事件),该事件里面找到对应的keycode并处理就…

JS相关知识总结(一)

总结下这段时间吸收的许多小知识,以备忘记后翻阅。 关于面向对象 面向对象特征: 具有唯一标识性具有状态具有行为 JS的面向对象和JAVA的实现思路不一样,JS是基于原型并非基于类。但是JS为了看起来更像JAVA,为此添加了一些特性…

WCF系列(二) -- 使用配置文件构建和使用WCF服务

当然,配置一个ServiceHost除了上面说的完全使用代码的方式,更好的方式是使用配置文件,把一些可能需要修改的属性跟代码分离,放到配置文件中,这样可以提供服务配置的灵活性,也更容易维护。 看看前面那个不用…

java读取文件方法

一、多种方式读文件内容。1、按字节读取文件内容2、按字符读取文件内容3、按行读取文件内容4、随机读取文件内容 Java代码 import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileReader; import java.io.IOExcept…

如何使用github搭建个人博客

1、去github官网注册个人帐号:没有的:猛戳这里去注册,比如我的账户名:wjf444128852,我的已经汉化(可在github里搜索github如何汉化有插件) 2、点击仓库-新建,仓库名字必须是:你的github帐号.git…

Spring Boot和Spring Data REST –通过REST公开存储库

使用Spring Boot和Spring Data REST,通过REST公开Spring Data存储库非常容易。 使用最少的代码,您可以创建遵循HATEOAS原理的JPA实体的REST表示。 我决定重用Spring PetClinic的JPA实体(业务层)作为本文的基础。 应用基础 PetCli…

记录一次cookie导致登录失败的惨案

现象描述: 前端登录成功后并没有从后端那里拿到登录信息,换句话说登录服务告诉我们登录成功了,但是后端却说我们没有登录成功。 背景: 因为前后端分离,所以前后端项目部署在两个子域名下。 因为要打通登录态&#…

sql中的遇到的有问题的

----题5&#xff1a;求出住在同一城市的顾客对--select city,count(cid) as 顾客的个数 from customers group by city--select --select distinct c1.cname,c2.cname,c1.city from customers c1, customers c2 where c1.cityc2.city and c1.cname<c2.cname select c1.cid,c…

nyoj 55 懒省事的小明 优先队列 multiset 还有暴力

懒省事的小明 时间限制&#xff1a; 3000 ms | 内存限制&#xff1a; 65535 KB难度&#xff1a; 3描述小明很想吃果子&#xff0c;正好果园果子熟了。在果园里&#xff0c;小明已经将所有的果子打了下来&#xff0c;而且按果子的不同种类分成了不同的堆。小明决定把所有的果子…

css3之3d导航

css3的新属性非常不错&#xff0c;目前IE除外其他浏览器都已支持 实现原理:比如元素a在hover时候可以改变元素b的状态。 效果如本农导航&#xff0c;欢迎采用和建议~ a:hover b{ 执行简单动画效果 } HTML <!DOCTYPE html><html lang"en"><head&…

jQuery Ajax – Servlets集成:构建完整的应用程序

网上有很多教程&#xff0c;它们解释了有关使用servlet和JSP页面进行Java Web开发的一些知识&#xff0c;但是&#xff0c;我从来没有找到对于初学者来说足够简洁&#xff0c;简单的教程。 这样的教程应该解释创建一个简单的Web应用程序的整个过程&#xff0c;包括前端&#xf…

ES6中块级作用域下的函数声明

背景 因为ES5的时候没有块级作用域&#xff0c;所以ES5规定不能再if这样的块中声明函数&#xff0c;但是为了兼容各大浏览器并没有严格遵守这条规定。 ES6的时候引入了块级作用域&#xff0c;规定在块级作用域中声明函数就相当于使用let来声明变量一样。但是又因为浏览器端的…

Oracle数据库卸载

Oracle数据库卸载 ORACLE数据库安装起来比较麻烦&#xff0c;卸载也不像微软的产品那样容易。对于ORACLE9的卸载&#xff0c;控制面板里是没有卸载程序的。可以从开始菜单—程序—Oracle Installation Products—Universal Installer 进入安装的界面&#xff0c;界面上有一个…

信息系统开发平台OpenExpressApp - 应用模型ApplicationModel

下图为OpenExpressApp的系统架构图&#xff0c;其中在应用模型是作为一种元数据贯穿于整个架构&#xff0c;应用模型运行在OpenExpressApp框架之上。应用模型是OEA的核心&#xff0c;理解好应用模型才能更好的使用OEA。 应用模型贯穿于整个架构层 模型关注what OEA希望从重复的…

SVN版本控制系统学习(中文配置)

先吐槽下往上搜索的一些SVN下载地址&#xff0c;里面乱七八糟啥都有&#xff0c;下载好后点击安装一不注意啥玩意都安装上了&#xff0c; 什么玩意都有&#xff0c;真心不明白这些推送者是怎么想的。搜集了一个WIN32的百度网盘下载地址&#xff1a; http://pan.baidu.com/s/1…

【译】nginx关于location部分

译&#xff1a; Syntax:location [ | ~ | ~* | ^~ ] uri { ... }location name { ... }Default:—Context:server, location 依据请求的URI进行配置。 在对以"%xx"形式的文本解码&#xff0c;对相对路径".“和”…"的格式化和两个或多个相邻斜杠压缩为单…

自定义汇编程序,Weaver和运行时的可插拔知识

作为贝叶斯工作的一部分&#xff0c;我对Kie进行了很多重构&#xff0c;使其具有清晰的扩展点。 我想确保可以完成贝叶斯系统的所有工作部件&#xff0c;而无需在现有内核中添加任何代码。 因此&#xff0c;现在每种知识类型都可以拥有自己的包&#xff0c;汇编器&#xff0c;…

动态代理

java动态代理 JAVA的动态代理 代理模式 代理模式是常用的java设计模式&#xff0c;他的特征是代理类与委托类有同样的接口&#xff0c;代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类&#xff0c;以及事后处理消息等。代理类与委托类之间通常会存在关联关系&…