摘要:为了方便,团队将一些集合在一起,并称之为。先看一下直观体验源代码配置编译后的代码通过对比可以看出,第二种方案直接从引入,避免自己定义,从而减少代码的体积。
Babel
Babel 是一个 JavaScript 编译器,它可以将ES6+语法编译为浏览器支持的ES5语法。要学好babel必须先理解相关的概念,但是你刚起步就去扣这些细节的话,很可能因为babel一些复杂而模糊的概念打击你的信息。所以我们先从最简单的开始,然后深入。
最简单的例子接下来我们尝试按照官方文档做一个最简单的例子
安装babel-cli
npm install --save-dev babel-cli
添加babel编译命令
"build": "babel src -d lib"
添加.babelrc配置文件
{
"presets": [],
"plugins": []
}
添加JS文件
// /src/main.js const fetch = args => args; console.log(Promise);
执行 npm run build,我们发现编译后的文件没有发生任何的改变,就是简单的原样输出
// /lib/main.js const fetch = args => args; console.log(Promise);
为什么呢?这是因为在.babelrc文件没有做任何的配置。我们一共使用了三个新特性,分别是常量申明const ,箭头函数=>,新全局变量Promise。接下来我门尝试将他们编译为ES5代码。
如上图所示,借助plugin可以实现我们的目标。接下来我们分别实现它:
const
原文链接 文档中说明:
babel-plugin-check-es2015-constants 这个插件仅仅是验证const变量的规则,比如不能重复申明,不可变等特性。
把它编译为ES5代码需要借助babel-plugin-transform-es2015-block-scoping
我们设置需要编译的代码为:
const fetch = args => args; fetch = 55; // 故意写错 console.log(Promise);
安装上面所需的两个plugin并改写.babelrc配置:
{
"presets": [],
"plugins": [
"check-es2015-constants",
"transform-es2015-block-scoping"
]
}
编译过程报错验证check-es2015-constants生效
我们修改需要编译的代码为:
const fetch = args => args; console.log(Promise);
再次编译成功
var fetch = args => args; console.log(Promise);
到这里我们已经成功的使用插件对const的语法和转译(Syntax和 transform)ES5化。是不是很开心呢? 接下来我们处理箭头函数=>。
arrow functions
同样安装对应的plugin :
npm install --save-dev babel-plugin-transform-es2015-arrow-functions
这里延用上面需要compile的源代码:
var fetch = args => args; console.log(Promise);
改写.babelrc配置文件:
{
"presets": [],
"plugins": [
"check-es2015-constants",
"transform-es2015-block-scoping",
"transform-es2015-arrow-functions"
]
}
编译结果:
var fetch = function (args) {
return args;
};
console.log(Promise);
编译成功,unbelievable, we did it!!!,是不是真的很简单?先别得意???,还有一个Promise没有解决呢。有惊喜哟!!!
Promise
我有一个问题:我特意将上面的两个例子放在一起,是因为他们都属于对新语法Syntax进行编译,而Promise是作为一个全局api的存在,在大部分浏览器中是不存在这个全局api的,如果让你来解决这个问题,你会怎么做?
你的答案:是的,没错!就是在不支持Promise的环境中实现Promise,在babel中被称为polyfill,注意它和shim的区别哦~
babel-polyfill 文档最简单的使用:
npm install --save-dev babel-polyfill
Use it by requiring it at the top of the entry point to your application or in your bundler config. ---在入口文件的最顶层作用域直接引入
到这里我们已经完成既定的3个目标,但是你有没有想过,随着我们ES6新特性的增加,plugin的长度也逐渐增加,可以遇见会有多长?,而且自己去找这些对应的plugin也是比较麻烦的。有没有傻瓜式的集成方法呢?您接着往下看。
Preset为了方便,Babel团队将一些Plugins集合在一起,并称之为preset。所以一个preset是一系列plugin的总和。按照年份划分:
ES2015/ ES-2016/ES2017 等等,还延伸了stage的概念,详情请查阅官网。
babel-preset-envA Babel preset that compiles ES2015+ down to ES5 by automatically determining the Babel plugins and polyfills you need based on your targeted browser or runtime environments.
不需要指定任何的plugin和polyfill,Babel preset 可以将ES6+的新语法向下编译为ES5代码,按照你指定的运行环境。具体的配置项请看官网。Without any configuration options, babel-preset-env behaves exactly the same as babel-preset-latest (or babel-preset-es2015, babel-preset-es2016, and babel-preset-es2017 together).
不需要做任何配置选项,它和babel-preset-latest表现一致,或者说和babel-preset-es2015, babel-preset-es2016, babel-preset-es20174个preset总和一致。
感觉是不是很牛逼!下面我们来尝试一个例子。为防止有任何的代码污染,我卸载所有npm package
最初的样子:
{
"name": "babelrc",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"build": "babel src -d lib"
},
"author": "",
"license": "ISC",
"devDependencies": {}
}
我安装时发现@babel/preset-env还处于bate版本,使用时还有一些问题,所以决定还是使用老版本。
(1)安装babel-preset-env
上图为babel-preset-env的一些依赖,主要为一些helper和plugin。
为了验证出babel-preset-env的是否满足要求,我新增了几行包括ES6的代码:
const fetch = args => args;
console.log(Promise);
// 新增一些代码
class G {
}
let [a, b, c] = [1, 2, 3];
(async () => {
await console.log(1)
})();
(2)配置.babelrc
{
"presets": ["env"],
"plugins": []
}
(3)编译结果
"use strict";
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var fetch = function fetch(args) {
return args;
};
console.log(Promise);
// 新增一些代码
var G = function G() {
_classCallCheck(this, G);
};
var a = 1,
b = 2,
c = 3;
_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return console.log(1);
case 2:
case "end":
return _context.stop();
}
}
}, _callee, undefined);
}))();
我就问还有谁???所有的新语法特性都被成功处理了。
Runtime官网文档
babel为源代码非实例方法(比如Object.assign)和 babel-runtime/helps下的工具函数自动引用了polyfill。这样可以避免全局空间的污染,非常适合用于JS库和工具包的实现。但是实例方法(比如someString.includes("target"))还是需要使用babel-polyfill。
如果你是新手,你可能没有注意到,babel编译时会在每个文件生成一些需要帮助函数,如果文件比较多,那么这些重复的代码会增加编译后的代码体积。下面是一个例子:
源代码
class G {
}
.babelrc配置
{
"presets": ["env"],
"plugins": []
}
编译代码
"use strict";
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var G = function G() {
_classCallCheck(this, G);
};
// _classCallCheck就是一个内部生成的帮助函数
为了优化编译体积,babel 团队推出了 babel-plugin-transform-runtime + babel-runtime来解决这个问题。先看一下直观体验:
源代码
class G {
}
.babelrc配置
{
"presets": ["env"],
"plugins": ["transform-runtime"]
}
编译后的代码:
"use strict";
var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck");
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var G = function G() {
(0, _classCallCheck3.default)(this, G);
};
通过对比可以看出,第二种方案直接从babel-runtime引入babel-runtime/helpers/classCallCheck,避免自己定义,从而减少代码的体积。
除了这个优点意外
babel-runtime
三个主要部分:core.js + helpers+ regenerator
当然除了上面的方法,通过按需引入 polyfills 和 transforms更能带来更多的体积优化。
减少对不必要浏览器的兼容来减少 polyfills 和 transforms的引入:
{
"presets": [
["env", {
"targets": {
// The % refers to the global coverage of users from browserslist
"browsers": [ ">0.25%", "not ie 11", "not op_mini all"]
}
}]
]
}
答疑
(1)可能你发现了我并没有安装babel-cli,为什么我能使用babel命令?
因为我在全局安装了babel。
(2) browserslistrc 配置更改之后 babel编译后的代码怎么没有改变。或者说 browserslistrc 影响babel编译的具体表现是怎么样的?
暂时我也不知道,我正在研究,后面更新。
参考[1] browserslist
[2] browserslist-example
[3] browserslist-queries
由于本人表达能力真的很差,表达不够清楚还望大家多多包涵。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/94563.html
摘要:快速体验安装依赖新建文件夹,在命令行里进入该文件夹,并执行如下命令生成文件是内置的一个,可通过命令行操作来编译文件。入门为了确保转换后的代码能正常的运行,最好在代码之前引入这是一个实现了部分特性的包。参考中文网入门 简介 Babel 是一个 JavaScript 编译器,可将我们代码中的 ES6 语法转换为 ES5 的语法,使我们的代码能在不支持 ES6 语法的环境中正常运行。配合一些...
摘要:首先安装使用时在文件头加载然后,就不需要手动对转码了。 原文转载自阮一峰教程 本文讲解如何在nodejs环境下使用babel将ES6代码转ES5以及运行ES6的js文件 配置.babelrc文件 首先安装es2015的presets字段 $ npm install --save-dev babel-preset-es2015 然后写入.babelrc { presets:[ ...
摘要:入门什么是是一个广泛使用的转码器,可以将代码转为代码,从而在现有环境执行。 babel6 入门 什么是babel Babel是一个广泛使用的转码器,可以将ES6代码转为ES5代码,从而在现有环境执行。 因为es6比es5的代码更为适合编写程序,但是因为历史的原因,现在普遍的浏览器并不支持es6代码(普遍支持es5),即如果你写es6代码之后,在浏览器上运行出错,因为浏览器的javas...
摘要:虽然够好用,奈何没有浏览器对其可以完全支持,本文书写时间,开发版号称已经支持的特性。开始安装本系列假定读者都有使用经验,如果还没有,赶紧去这里了解并安装吧。到此,我们的已经准备就绪。 通过前面章节的讲解,大家对ES2015的一些新语法有了初步的理解,之前我们的测试代码都可以直接放入 Chrome Console 中直接运行,为了更好的学习后面的面向对象和模块开发,我先用一章介绍一下 B...
摘要:概述开坑系列文章,不知道会写到什么程度,毕竟写文章并不在行,存在当做笔记做,先不讲理论,实践先行。 0x000 概述 开坑 react 系列文章,不知道会写到什么程度,毕竟写文章并不在行,存在当做笔记做,先不讲理论,实践先行。 0x001 创建项目 $ mkdir 0x001-helloworld $ cd 0x001-helloworld $ yarn init -y 0x0002 ...
阅读 2028·2021-11-24 09:39
阅读 1861·2021-11-22 15:22
阅读 1256·2021-09-27 13:36
阅读 3734·2021-09-24 10:34
阅读 3712·2021-07-26 23:38
阅读 2777·2019-08-29 16:44
阅读 1117·2019-08-29 16:39
阅读 1284·2019-08-29 16:20