共计 7715 个字符,预计需要花费 20 分钟才能阅读完成。
译文:Babel.js Guide -Part 1- The Absolute Must-Know Basics: Plugins, Presets, And Config
本文将讲述:
- Babel 是什么以及怎么在日常开发中应用它?
- presets and plugins 是什么及区别,在 babel 执行中,他们的执行程序是什么?
尽管原文题目看似是一个系列,但作者仿佛没有持续,但我曾经想好了下一部分要写的内容;非专业翻译,夹带本人了解,有小改变。
Babel 是什么
babel 是一个收费开源的 JavaScript 编译库. 它依据你的配置将代码转化成各式各样的 JS 代码。
最常见的应用形式就是将古代语法 JavaScript es6+ 编写的代码 转化成 es5,从而兼容更多的浏览器(特地是 IE),上面以 Babel 转换 es6 箭头函数 为 es5 函数的为例。
// The original code
const foo = () => console.log('hello world!');
转移后
// The code after babel transpilation
var foo = function foo() {return console.log('hello world!');
};
你能够在这里在线尝试
应用 Babel
在线 Repl
这是应用 Babel 的最简略办法。这兴许不是一个十分实用的工具,然而是最快的测试或者试验 Babel 如何工作的工具, 在线 Repl 地址。
构建库
应用 Babel 的最风行办法是应用 Webpack
,Gulp
或Rollup
等构建库进行打包构建。每个形式都应用 Babel 作为构建的一部分来实现本人的构建过程。
比方,咱们最罕用的 webpack:
{
...
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {plugins: ['@babel/plugin-transform-arrow-functions']
}
}
}
]
},
...
}
库罕用的构建工具:Rollup
rollup.rollup({
...,
plugins: [
...,
babel({plugins: ['@babel/plugin-transform-arrow-functions']
}),
...
],
...
}).then(...)
脚手架 cli
除了依赖构建库,也能够间接用命令行依赖官网提供的 @babel/cli 包来编译 NIIT 的代码:
# install the core of babel and it's cli interface
npm install @babel/core @babel/cli
# use the babel command line
babel script.js --out-file script-compiled.js
Babel Plugins
Babel 是通过 插件
配置的。开箱即用,Babel 不会更改您的代码。没有插件,它基本上是这样的:
// parse -> generate, 大白话就是英翻中,中翻英
const babel = code => code;
通过 Babel 插件运行代码,您的代码将转换为新代码,如下所示:
// parse -> do something -> generate,大白话就是英翻中,添枝加叶,中翻英
const babel = code => babelPlugin2(babelPlugin1(code));
Babel Presets
您能够独自增加 Babel 插件列表,然而通常更不便的办法是应用 Babel presets。
Babel presets 联合一系列插件的汇合。传递给 presets 的选项会影响其聚合的插件, 这些选项将管制应用哪些插件以及这些插件的配置。
比方,咱们后面看到的 @babelplugin-transform-arrow-functions
插件是@babel/preset-env
presets 的一部分。
@babel/preset-env
可能是最受欢迎的 presets。它依据用户传递给预设的配置(比方 browsers:指标浏览器 / 环境), 将古代 JavaScript(即 ES Next)转换为较旧的 JavaScript 版本。
比方:它能够将()=> arrowFunctions,{…detructuring} 和 class {}转换为旧版浏览器反对的 JavaScript 语法,举个????, 指标浏览器为 IE11:
// 新版语法
class SomeClass {constructor(config){
this.someFunction = params => {console.log('hello world!', {...config, ...params});
}
}
someMethod(methodParams){this.someFunction(methodParams);
}
someOtherMethod(){console.log('hello some other world');
}
}
编译后:
// explained here: https://www.w3schools.com/js/js_strict.asp
"use strict";
// this is a babel helper function injected by babel to mimic a {...destructuring} syntax
function _objectSpread(target) {for (var i = 1; i < arguments.length; i++) {var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') {ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) {_defineProperty(target, key, source[key]); }); } return target; }
// this is a babel helper function injected by babel for a faster-than-native property defining on an object
// very advanced info can be found here:
// https://github.com/babel/babel/blob/3aaafae053fa75febb3aa45d45b6f00646e30ba4/packages/babel-helpers/src/helpers.js#L348
function _defineProperty(obj, key, value) {if (key in obj) {Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true}); } else {obj[key] = value; } return obj; }
// this is a babel helper function that makes sure a class is called with the "new" keyword like "new SomeClass({})" and not like "SomeClass({})"
function _classCallCheck(instance, Constructor) {if (!(instance instanceof Constructor)) {throw new TypeError("Cannot call a class as a function"); } }
// like "_defineProperty" above, but for multiple props
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); } }
// used by babel to create a class with class functions
function _createClass(Constructor, protoProps, staticProps) {if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
var SomeClass =
/*#__PURE__*/ // this marks the function as pure. check https://webpack.js.org/guides/tree-shaking/ for more info.
function () {
// the class got converted to a function
function SomeClass(config) {
// make sure a class is called with the "new" keyword
_classCallCheck(this, SomeClass);
// someFunction is set on SomeClass
this.someFunction = function (params) {// notice how the {...config, ...params} became _objectSpread({}, config, params) here
console.log('hello world!', _objectSpread({}, config, params));
};
}
// this function adds the class methods to the transpiled class created above
_createClass(SomeClass, [
{
key: "someMethod",
value: function someMethod(methodParams) {this.someFunction(methodParams);
}
},
{
key: "someOtherMethod",
value: function someOtherMethod() {console.log('hello some other world');
}
}
]);
return SomeClass;
}();
对于更简单的构建要求,配置将应用我的项目根目录中的 babel.config.js 文件。因为是 JavaScript 文件,因而比.babelrc 更加灵便。例如:
module.exports = function (api) {
// Only execute this file once and cache the resulted config object below for the next babel uses.
// more info about the babel config caching can be found here: https://babeljs.io/docs/en/config-files#apicache
api.cache.using(() => process.env.NODE_ENV === "development")
return {
presets: [
// Use the preset-env babel plugins
'@babel/preset-env'
],
plugins: [
// Besides the presets, use this plugin
'@babel/plugin-proposal-class-properties'
]
}
}
@babel/preset-env
不同配置,编译出的代码可能大不一样,比方当配置为:latest 10 Chrome versions
是,下面一段代码编译后果与编译前统一,因为下面的个性,chrrome 都反对;但如果将 10 调整为 30,40 时,你会发现,编译的代码将会越来越多;能够点击这里尝试一下:
配置
Babel Plugins and Presets
是十分重要的概念,Babel 的配置由 Plugins and Presets 组合而成(也能够应用其余几个高级属性);
简略的配置,能够间接应用.babelrc,babelrc 是一种 JSON5 文件(和 JSON 一样,但其容许正文),被搁置在我的项目根目录下,比方上面这样:
// Comments are allowed as opposed to regular JSON files
{
presets: [
// Use the preset-env babel plugins
'@babel/preset-env'
],
plugins: [
// Besides the presets, use this plugin
'@babel/plugin-proposal-class-properties'
]
}
对于更简单的配置,个别应用 babel.config.js
文件来代替 .babelrc
文件,因为他是 js 文件,所以比 .babelrc
配置更灵便,举个例子:
module.exports = function (api) {
// Only execute this file once and cache the resulted config object below for the next babel uses.
// more info about the babel config caching can be found here: https://babeljs.io/docs/en/config-files#apicache
api.cache.using(() => process.env.NODE_ENV === "development")
return {
presets: [
// Use the preset-env babel plugins
'@babel/preset-env'
],
plugins: [
// Besides the presets, use this plugin
'@babel/plugin-proposal-class-properties'
]
}
}
一些配置文件可能非常复杂, 例如: Babel 我的项目自身的 babel.config.js。莫慌!浏览本指南系列后,您将晓得此简单配置的每一行的意义(看,有头牛在天上飞)。
Babel Plugins and Presets 执行程序
如果您在配置中混合应用了 Plugins 和 Presets,Babel 将按以下程序利用它们:
- 首先从上到下利用插件;
- 而后,将预设利用在插件之后,从下到上;
举个????:
{
presets: ['@babel/preset-5', // ↑ ** End Here ** Last preset to apply it's plugins *after* all the plugins below finished to run'@babel/preset-4', // ↑'@babel/preset-3', // ↑ 2'@babel/preset-2', // ↑'@babel/preset-1', // ↑ First preset to apply it's plugins *after* all the plugins below finished to run],
plugins: [
'@babel/plugin-1', // ↓ >>> Start Here <<< First plugin to transpile the code.
'@babel/plugin-2', // ↓
'@babel/plugin-3', // ↓ 1
'@babel/plugin-4', // ↓
'@babel/plugin-5', // ↓ Last plugin to transpile the code before the preset plugins are applied
]
}
另外,值得一提的是,每个 Presets 中的插件也自上而下利用。
以正确的程序配置 Plugins 和 Presets 十分重要!正确的程序可能会放慢翻译速度,谬误的程序可能会产生不须要的后果或者导致谬误。
可能下面的???? 不够实在,那就来个实在的吧:
{
"presets": [
"@babel/preset-env",
"@babel/preset-react",
],
"plugins": [["@babel/plugin-proposal-decorators", { "legacy": true}],
]
}
decorators
是装璜器语法,当初还处于 stage- 3 阶段难产,而 JSX 则是 React 的专有语法;如果没有 @babel/plugin-proposal-decorators
和 @babel/preset-react
先编译,间接运行@babel/preset-env
编译,就会报@
或 <div>
有效的语法标识,所有正确的配置插件和插件程序是如许重要。
Babel Plugins and Presets 选项
下面提到过给 @babel/preset-env
设置不同的 browsers 选项,会失去不同的编译后果;通过将选项包装在数组中并向其中增加选项,能够将选项配置传递给 Babel Plugins and Presets,比方位于 @babel/preset-env
前面的对象就是一个选项配置,通知编译的指标是兼容到 chrome 58 版本和 IE11:
{
presets: [
// Notice how @babel/preset-env is wrapped in an array with an options object
['@babel/preset-env', {
"targets": {
"chrome": "58",
"ie": "11"
}
}],
'@babel/some-other-preset'
]
}
@babel/preset-env
根本是我的项目编译必选的 Presets,除了 targets,还有 useBuiltIns,esmodules,modules 等常见选项,还有更多对于配置可参考官网
最初
对于指引,就这么多,将在不久后推出进阶篇, 对于 babel-runtime 与 babel-polyfill。