babel7 学习笔记(1)
网站资源
什么是 Babel ?
- Babel 是一个 JavaScript 编译器
- Babel 是一个工具链,主要用于在旧的浏览器或环境中将 ECMAScript 2015+ 代码转换为向后兼容版本的 JavaScript 代码:
- 转换语法
- Polyfill 实现目标环境中缺少的功能 (通过 @babel/polyfill)
- 源代码转换 (codemods)
- 更多!(查看视频)
// Babel Input: ES2015 arrow function
[1, 2, 3].map((n) => n + 1);
// Babel Output: ES5 equivalent
[1, 2, 3].map(function(n) {
return n + 1;
});
有关编译器的精彩教程,请查看超级微型编译器,它还解释了 Babel 本身如何在高级语言上工作。
ES2015 及其他
可插拔
- Babel 是用插件构建的。你可以使用现有插件编写自己的转换管道或编写自己的插件。通过使用或创建 preset 轻松使用一组插件。了解更多 →
- 使用 astexplorer.net 动态创建插件或使用 generator-babel-plugin 生成插件模板。
// A plugin is just a function
export default function ({types: t}) {
return {
visitor: {
Identifier(path) {
let name = path.node.name; // reverse the name: JavaScript -> tpircSavaJ
path.node.name = name.split('').reverse().join('');
}
}
};
}
可调试
- 支持 Source map ,因此你可以轻松调试编译过的代码。
规范性
- Babel 试图尽可能地遵循 ECMAScript 标准。为了平衡性能,它也可能有特定的一些选项,以便可以更符合规范。
压缩性
- Babel 尝试使用尽可能少的代码而不依赖于庞大的运行时环境。
- 有些情况可能很难达到,因此为了保证可读性、文件大小以及(运行)速度,会针对特定转换牺牲一些合规性,即提供 “loose” 选项。
Babel常用包和插件
@babel/cli
-
安装
- 虽然你 可以 在你的机器上全局安装 Babel CLI, 但根据单个项目进行本地安装会更好一些。
- 这样做有两个主要的原因:
- 同一机器上的不同的项目可以依赖不同版本的 Babel, 这允许你一次更新一个项目。
- 这意味着在你的工作环境中没有隐含的依赖项。它将使你的项目更方便移植、更易于安装。
- 我们可以通过以下命令本地安装 Babel CLI:
npm install --save-dev @babel/core @babel/cli
注意: 如果你没有一个 package.json, 在安装之前请新建一个。这可以保证 npx 命令产生合适的交互。
- 在完成安装之后,你的 package.json 文件应该包括:
{ "devDependencies": { + "@babel/cli": "^7.0.0", + "@babel/core": "^7.0.0" } }
用法
- 我们将把我们的指令放在本地版本的 npm 脚本中,而不是直接通过命令行来运行 Babel.
- 简单的在你的 package.json 中添加一个 “scripts” 属性并将 babel 命令放在它的 build 属性中。
{ "name": "my-project", "version": "1.0.0", + "scripts": { + "build": "babel src -d lib" + }, "devDependencies": { "babel-cli": "^6.0.0" } }
- 现在从我们的终端可以运行以下命令:
npm run build
- 这会按照和之前一样的方式来运行 Babel 并将输出放在 lib 目录下,唯一不同在于我们现在使用了一个本地拷贝。
- 另外,你可以在 node_modules 中引用 babel 命令。
./node_modules/.bin/babel src -d lib
创建.babelrc 配置文件
- 非常棒!虽然已经配置好了 Babel ,但并没有让它真正生效。在项目的根目录中创建一个 .babelrc 文件并启用一些插件。
- 首先,你可以使用转换 ES2015+ 的 env preset 。
npm install @babel/preset-env --save-dev
- 为了让 preset 生效,你需要像下面这样定义你的 .babelrc 文件:
{ "presets": ["@babel/preset-env"] }
编译前后
// 前 const fun = () => console.log('hello word!'); // 后 "use strict"; var fun = function fun() { return console.log('hello word!'); };
@babel/plugin-transform-block-scoping
- @babel/preset-env 已包含 该插件
- 文档地址
- 此插件还验证所有const变量。 重新分配常量是一个运行时错误,它将为那些插入必要的错误代码。
- 安装
npm install --save-dev @babel/plugin-transform-block-scoping
- 配置
{
"plugins": ["@babel/plugin-transform-block-scoping"]
}
@babel/plugin-transform-classes
- @babel/preset-env 已包含 该插件
- 文档地址
- 安装
npm install --save-dev @babel/plugin-transform-classes
- 配置
// without options
{
"plugins": ["@babel/plugin-transform-classes"]
}
// with options
{
"plugins": [
["@babel/plugin-transform-classes", {
"loose": true
}]
]
}
- 示例
- 源码
class Test { constructor(name) { this.name = name; } logger () { console.log("Hello", this.name); } }
- 编译后
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } var Test = /*#__PURE__*/ function () { function Test(name) { _classCallCheck(this, Test); this.name = name; } _createClass(Test, [{ key: "logger", value: function logger() { console.log("Hello", this.name); } }]); return Test; }();
@babel/polyfill
- 文档地址
- Babel包含一个polyfill,它包含一个自定义的再生器运行时和core-js。这意味着您可以使用新的内置函数(如Promise或WeakMap),静态方法(如Array.from或Object.assign),实例方法(如Array.prototype.includes)和生成器函数(假设您使用的是再生器插件)。 为了做到这一点,polyfill添加到全局范围以及像String这样的本机原型。
- 安装
npm install --save @babel/polyfill
因为这是一个polyfill(它将在你的源代码之前运行),我们需要它作为依赖,而不是devDependency
- polyfill是为方便起见而提供的,但您应该将它与@ babel / preset-env和useBuiltIns选项一起使用,这样它就不会包含并不总是需要的整个polyfill。 否则,我们建议您手动导入单个polyfill。
require("core-js/modules/es6.array.copy-within");
require("core-js/modules/es6.array.fill");
require("core-js/modules/es6.array.find");
require("core-js/modules/es6.array.find-index");
require("core-js/modules/es7.array.flat-map");
require("core-js/modules/es6.array.from");
require("core-js/modules/es7.array.includes");
require("core-js/modules/es6.array.iterator");
require("core-js/modules/es6.array.of");
require("core-js/modules/es6.array.sort");
require("core-js/modules/es6.array.species");
require("core-js/modules/es6.date.to-json");
require("core-js/modules/es6.date.to-primitive");
require("core-js/modules/es6.function.has-instance");
require("core-js/modules/es6.function.name");
require("core-js/modules/es6.map");
require("core-js/modules/es6.math.acosh");
require("core-js/modules/es6.math.asinh");
require("core-js/modules/es6.math.atanh");
require("core-js/modules/es6.math.cbrt");
require("core-js/modules/es6.math.clz32");
require("core-js/modules/es6.math.cosh");
require("core-js/modules/es6.math.expm1");
require("core-js/modules/es6.math.fround");
require("core-js/modules/es6.math.hypot");
require("core-js/modules/es6.math.imul");
require("core-js/modules/es6.math.log1p");
require("core-js/modules/es6.math.log10");
require("core-js/modules/es6.math.log2");
require("core-js/modules/es6.math.sign");
require("core-js/modules/es6.math.sinh");
require("core-js/modules/es6.math.tanh");
require("core-js/modules/es6.math.trunc");
require("core-js/modules/es6.number.constructor");
require("core-js/modules/es6.number.epsilon");
require("core-js/modules/es6.number.is-finite");
require("core-js/modules/es6.number.is-integer");
require("core-js/modules/es6.number.is-nan");
require("core-js/modules/es6.number.is-safe-integer");
require("core-js/modules/es6.number.max-safe-integer");
require("core-js/modules/es6.number.min-safe-integer");
require("core-js/modules/es6.number.parse-float");
require("core-js/modules/es6.number.parse-int");
require("core-js/modules/es6.object.assign");
require("core-js/modules/es7.object.define-getter");
require("core-js/modules/es7.object.define-setter");
require("core-js/modules/es7.object.entries");
require("core-js/modules/es6.object.freeze");
require("core-js/modules/es6.object.get-own-property-descriptor");
require("core-js/modules/es7.object.get-own-property-descriptors");
require("core-js/modules/es6.object.get-own-property-names");
require("core-js/modules/es6.object.get-prototype-of");
require("core-js/modules/es7.object.lookup-getter");
require("core-js/modules/es7.object.lookup-setter");
require("core-js/modules/es6.object.prevent-extensions");
require("core-js/modules/es6.object.to-string");
require("core-js/modules/es6.object.is");
require("core-js/modules/es6.object.is-frozen");
require("core-js/modules/es6.object.is-sealed");
require("core-js/modules/es6.object.is-extensible");
require("core-js/modules/es6.object.keys");
require("core-js/modules/es6.object.seal");
require("core-js/modules/es6.object.set-prototype-of");
require("core-js/modules/es7.object.values");
require("core-js/modules/es6.promise");
require("core-js/modules/es7.promise.finally");
require("core-js/modules/es6.reflect.apply");
require("core-js/modules/es6.reflect.construct");
require("core-js/modules/es6.reflect.define-property");
require("core-js/modules/es6.reflect.delete-property");
require("core-js/modules/es6.reflect.get");
require("core-js/modules/es6.reflect.get-own-property-descriptor");
require("core-js/modules/es6.reflect.get-prototype-of");
require("core-js/modules/es6.reflect.has");
require("core-js/modules/es6.reflect.is-extensible");
require("core-js/modules/es6.reflect.own-keys");
require("core-js/modules/es6.reflect.prevent-extensions");
require("core-js/modules/es6.reflect.set");
require("core-js/modules/es6.reflect.set-prototype-of");
require("core-js/modules/es6.regexp.constructor");
require("core-js/modules/es6.regexp.flags");
require("core-js/modules/es6.regexp.match");
require("core-js/modules/es6.regexp.replace");
require("core-js/modules/es6.regexp.split");
require("core-js/modules/es6.regexp.search");
require("core-js/modules/es6.regexp.to-string");
require("core-js/modules/es6.set");
require("core-js/modules/es6.symbol");
require("core-js/modules/es7.symbol.async-iterator");
require("core-js/modules/es6.string.anchor");
require("core-js/modules/es6.string.big");
require("core-js/modules/es6.string.blink");
require("core-js/modules/es6.string.bold");
require("core-js/modules/es6.string.code-point-at");
require("core-js/modules/es6.string.ends-with");
require("core-js/modules/es6.string.fixed");
require("core-js/modules/es6.string.fontcolor");
require("core-js/modules/es6.string.fontsize");
require("core-js/modules/es6.string.from-code-point");
require("core-js/modules/es6.string.includes");
require("core-js/modules/es6.string.italics");
require("core-js/modules/es6.string.iterator");
require("core-js/modules/es6.string.link");
require("core-js/modules/es7.string.pad-start");
require("core-js/modules/es7.string.pad-end");
require("core-js/modules/es6.string.raw");
require("core-js/modules/es6.string.repeat");
require("core-js/modules/es6.string.small");
require("core-js/modules/es6.string.starts-with");
require("core-js/modules/es6.string.strike");
require("core-js/modules/es6.string.sub");
require("core-js/modules/es6.string.sup");
require("core-js/modules/es7.string.trim-left");
require("core-js/modules/es7.string.trim-right");
require("core-js/modules/es6.typed.array-buffer");
require("core-js/modules/es6.typed.int8-array");
require("core-js/modules/es6.typed.uint8-array");
require("core-js/modules/es6.typed.uint8-clamped-array");
require("core-js/modules/es6.typed.int16-array");
require("core-js/modules/es6.typed.uint16-array");
require("core-js/modules/es6.typed.int32-array");
require("core-js/modules/es6.typed.uint32-array");
require("core-js/modules/es6.typed.float32-array");
require("core-js/modules/es6.typed.float64-array");
require("core-js/modules/es6.weak-map");
require("core-js/modules/es6.weak-set");
require("core-js/modules/web.timers");
require("core-js/modules/web.immediate");
require("core-js/modules/web.dom.iterable");
require("regenerator-runtime/runtime");
- webpack打包配置
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "entry",
"targets": "> 0.25%, not dead"
}
]
]
}