使用Babel进行JS转码
Babel是一个广泛使用的JavaScript语法转换器(syntax transformer),它可以将ES6编译为更被广泛支持的ES5,以便在浏览器中运行。
默认的,Babel仅仅进行语法的转换,为了支持ES6中大量新的API,需要使用Babel的垫片库。该垫片库在内部使用了core.js和regenerator。
Babel也对React的JSX提供了支持,它可以转换JSX语法、去除类型注解。
通过对Source map的支持,你可以在Chrome浏览器中轻松的调试编译后的代码。
可以使用npm来安装Babel,官方提供了几个转换规则预设(preset),可以按需安装:
1 2 3 4 5 6 7 8 9 10 11 12 |
# 使用 --save-dev安装,可以让不同工程使用不同的babel版本 # 支持通过命令行调用babel,全局安装 npm install --global babel-cli # 安装垫片库 npm install --save-dev babel-polyfill # 支持对ES6进行转码 npm install --save-dev babel-preset-es2015 # 支持对React进行转码 npm install --save-dev babel-preset-react # 支持对ES7进行转换,可以选择0-3这四个阶段之一 npm install --save-dev babel-preset-stage-2 |
Babel依赖于当前目录中名为 .babelrc 的配置文件来提供配置信息,通常把该此配置文件放在工程的根目录下。使用该文件来指定使用的规则预设、插件:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
{ "presets": [], "plugins": [] } // 示例: { "presets": [ "es2015", "react", "stage-2" ], "plugins": [] } |
Babel提供了一个工具,用于基于命令行执行转码。示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# index.es6内容如下: # let name = 'Alex'; # ((msg) => console.log(msg))(name); # 转码单个文件,打印到标准输出 babel index.es6 # var name = 'Alex'; # (function (msg) { # return console.log(msg); # })(name); # 转码单个文件,-o / --out-file 指定输出文件路径 babel index.es6 -o index.js # 转码整个目录,-d / --out-dir 指定输出目录路径 babel src -d lib # 转码的同时声车个source map文件供调试用 babel src -d lib -s |
使用全局安装的Babel的缺点是,所有工程都被限定为一致的Babel版本。可以为当前工程安装局部的Babel命令行,并集成到npm构建流程中:
1 2 |
# 局部安装 npm install --save-dev babel-cli |
更改package.json:
1 2 3 4 5 6 7 8 |
{ "devDependencies": { "babel-cli": "^6.0.0" }, "scripts": { "build": "babel src -d lib" }, } |
然后可以执行下面的命令来转码:
1 |
npm run build |
包babel-cli自带了一个交互式解释器babel-node,它支持Node.js的REPL环境的全部功能,并且可以直接运行(不需要转码)ES6代码。
在命令行直接输入 babel-node 即可进入交互式环境。如果附加脚本文件名作为参数,可以运行ES6脚本。
该工具为require函数添加一个钩子,每当通过require加载js|jsx|es|es6后缀的文件时,都会自动的实时转码(因此仅适用于开发环境)。执行下面的命令安装此工具:
1 |
npm install --save-dev babel-register |
在代码中,你需要:
1 2 3 |
// 首先要加载babel-register模块 require("babel-register"); require("./index.es6"); |
要在WebStorm中基于Babel直接调试ES6,可以参考下面的运行配置:
如果需要通过API来进行转码,可以安装该包:
1 |
npm install babel-core --save |
使用该包的方法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
var babel = require('babel-core'); // 转换字符串中的代码,返回值结构: { code, map, ast } babel.transform('...', options); // 异步文件转码 babel.transformFile('filename.es6', options, function(err, result) { result; // 结构:{ code, map, ast } }); // 同步文件转码,返回值结构: { code, map, ast } babel.transformFileSync('filename.js', options); // 实例: var es6Code = 'let x = n => n + 1'; var es5Code = require('babel-core').transform(es6Code, { presets: ['es2015'] }).code; |
缺省情况下,Babel仅仅转换JavaScript语法而不转换ES6的API。Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise等全局类型以及Object.assign等方法,都不会转码。
要让ES5环境支持ES6中的API,需要安装一个垫片库:
1 |
npm install --save babel-polyfill |
然后,在你的源码头部添加:
1 2 3 |
import 'babel-polyfill'; // 或者 require('babel-polyfill'); |
Babel可以用于浏览器环境,但是从Babel 6.0开始,需要利用工具构建出浏览器版本。
如果不想进行构建,可以使用5.x版本:
1 |
npm install babel-core@5 |
执行上述命令后,到node_modules/babel-core子目录中,可以找到browser.js,这就是Babel提供的浏览器环境转换器。你需要将此脚本引入网页:
1 2 3 4 5 |
<script src="node_modules/babel-core/browser.js"></script> <!-- 注意type必须为text/babel --> <script type="text/babel"> // 在这里编写ES6代码 </script> |
注意:上面是运行时转换,对性能有影响。在生产环境下应该加预转码脚本。
可以在开发时利用Babel + Browserify,将ES6代码转换为浏览器可用的脚本。
Browserify是一个npm包,支持在浏览器中使用Node.js的 require() 函数。 Browserify并非唯一选择,JSPM、System.js、Webpack、require.js等可以代替它。
Babelify是一个Browserify转换器,转换器在运行Browserify之前被执行,可以对代码进行预处理。Babelify执行的预处理就是Babel转码。
执行下面的命令安装Babelify:
1 |
npm install --save-dev babelify |
调用Browserify进行转换:
1 |
browserify script.es6 -o script.js -t [ babelify --presets [ es2015 ] ] |
浏览器只需要引用转换后的script.js文件就可以了。你可以进一步修改package.json:
1 2 3 4 5 |
{ "browserify": { "transform": [["babelify", { "presets": ["es2015"] }]] } } |
这样就不需要每次调用都输入转换器参数了。
安装Babel的Webpack加载器、Babel核心,以及需要使用的预设:
1 |
npm install babel-loader babel-core babel-preset-es2015 --save-dev |
使用下面的配置来启用Babel加载器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// Webpack 1.x配置 entry: ['babel-polyfill', './index.js'], // 使用Babel垫片,需要加入到入口点 module: { loaders: [ { test: /\.js$/, exclude: /(node_modules|bower_components)/, loader: 'babel-loader', // 使用此属性,传递Babel选项 query: { presets: [ 'es2015' ] }, // 或者嵌入选项到loader字段: loader: 'babel-loader?presets[]=es2015' // 也可以从 .babelrc 读取选项 } ] } |
运行Babel命令行时,提示该错误,说明当前工程没有安装.babelrc中声明的规则预设。
导入模块时出现该问题,可能是import/export的写法有问题,例如:
- 应该使用import {***}时使用了import ***
- 对基于export语句导出的模块,使用require进行导入
Leave a Reply