初始化一个项目
mkdir babeljs
cd babeljs
npm init -y
安装@babel/cli
和@babel/core
注意是开发依赖:
npm i -D @babel/cli @babel/core
按照官方的说法:如果不手动指定安装@babel/core
,npx会安装babel6.x。
创建一个es6
文件
cat <<EOF > 01.js
const a = 0
const b = '1'
export { a }
export default b
EOF
用npx跑一下
% npx babel 01.js
const a = 0;
const b = '1';
export { a };
export default b;
很贴心,给每行都加了分号。
使用presets
安装一个大家都极为熟悉的npm包:@babel/preset-env
npm i -D @babel/preset-env
然后在npx指定加载这个preset:
% npx babel 01.js --presets=@babel/preset-env
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = exports.a = void 0;
var a = 0;
exports.a = a;
var b = '1';
var _default = b;
exports["default"] = _default;
就很熟悉的味道。
支持JSX
先改一下01.js
的代码:
const a = 0
const b = '1'
const c = <h1>Hello</h1>
export { a, c }
export default b
注意新增了变量c,返回一个jsx节点。
如果我们还使用之前的编译命令,就会报错了,因为语法解析认为这是错误的js代码:
% npx babel 01.js --presets=@babel/preset-env
SyntaxError: /Users/kema/git/exp2fun/babeljs/01.js: Support for the experimental syntax 'jsx' isn't currently enabled (3:11):
1 | const a = 0
2 | const b = '1'
> 3 | const c = <h1>Hello</h1>
| ^
4 | export { a, c }
5 | export default b
6 |
Add @babel/preset-react (https://git.io/JfeDR) to the 'presets' section of your Babel config to enable transformation.
按照提示,安装@babel/preset-react
并执行:
npx babel 01.js --presets=@babel/preset-env,@babel/preset-react
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = exports.c = exports.a = void 0;
var a = 0;
exports.a = a;
var b = '1';
# 所以页面顶部要先 import React from 'react'
var c = /*#__PURE__*/React.createElement("h1", null, "Hello");
exports.c = c;
var _default = b;
exports["default"] = _default;
可以看到,这里的变量c被转成了react
组件。
顾名思义,@babel/preset-react
是转react组件,你猜有没有@babel/preset-vue
?
jsx -> vue
有但不叫这个名字,而是@vue/babel-preset-jsx
:
npm i -D @vue/babel-preset-jsx
期待一下吧:
% npx babel 01.js --presets=@babel/preset-env,@vue/babel-preset-jsx
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = exports.c = exports.a = void 0;
var a = 0;
exports.a = a;
var b = '1';
var c = h("h1", ["Hello"]);
exports.c = c;
var _default = b;
exports["default"] = _default;
完美。
通过上面的几个小栗子能看到,在不同preset的加持下,jsx可以转成不同框架下的组件。
来看一下jsx在react下的完整形态:
import React from 'react'
const a = 0
const b = '1'
const c = <h1>Hello</h1>
export { a, c }
export default b
% npx babel 01.js --presets=@babel/preset-env,@babel/preset-react
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = exports.c = exports.a = void 0;
var _react = _interopRequireDefault(require("react"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
var a = 0;
exports.a = a;
var b = '1';
var c = /*#__PURE__*/_react["default"].createElement("h1", null, "Hello");
exports.c = c;
var _default = b;
exports["default"] = _default;
plugins
babel的插件原理和使用还是很好理解的,而且官方插件就很丰富。日常的话,当伸手党就可以。
这里拿一个官方插件@babel/plugin-proposal-decorators
简单做个例子:
// 02.js
@annotation
class MyClass {}
function annotation(target) {
target.annotated = true;
}
配置插件的时候,插件参数通过命令行就不好去配置了,所以这里我们用.babelrc
来配置转换插件及参数:
{
"plugins": [
[
"@babel/plugin-proposal-decorators",
{
"decoratorsBeforeExport": true
}
]
]
}
编译
% npx babel 02.js
转出来的代码很多,基本上都是polyfill的操作。
当然也可以配合presets
参数使用
npx babel 02.js --presets=@babel/preset-env
转成es5,node就可以直接用了。
more
更多配置项说明,请见官方文档。