一、基础概念
Babel 是 JavaScript 的编译器,通过 Babel 可以将我们写的最新 ES 语法的代码轻松转换成任意版本的 JavaScript 语法。随着浏览器逐步支持 ES 标准,我们不需要改变代码,只需要修改 Babel 配置即可以适配新的浏览器。
主要类库:
1)@babel/core
2)@babel/cli Babel 自己的 CLI(Command-Line Interface,命令行界面) 工具
3)@babel/preset-env插件组合
4)@babel/polyfill
5)@babel/runtime Babel 插件组合@babel/plugin-transform-runtime
二、深入部分
2.1 Babel基础使用示例
2.1.1 新建项目文件夹,创建一个babel.js文件:
// babel.js
[1, 2, 3].map(n => n ** 2);
下载Babel依赖:
npm i -D @babel/core @babel/cli
然后执行npx babel babel.js则会看到输出的内容:
可以看到输出的内容跟源文件内容没有区别,这是因为没有加转换规则,下面安装@babel/preset-env。然后执行 CLI 的时候添加--presets flag:
# 安装 preset-env
npm i -D @babel/preset-env
# 执行 CLI 添加--presets
npx babel babel.js --presets=@babel/preset-env
可以看到最终输出的代码就是转换为 ES5 的代码了:
"use strict";
// babel.js
[1, 2, 3].map(function (n) {
return Math.pow(n, 2);
});
如果要输出结果到固定文件,可以使用--out-file
或-o
参数:npx babel babel.js -o output.js
:
2.2 除了使用命令行配置 flag 之外,Babel 还支持配置文件,配置文件支持两种:
- 使用
package.json
的babel
属性; - 在项目根目录单独创建
.babelrc
或者.babelrc.js
文件。
// package.json
{
"name": "my-package",
"version": "1.0.0",
"babel": {
"presets": ["@babel/preset-env"]
}
}
// .babelrc
{
"presets": ["@babel/preset-env"]
}
Babel会在正在被转义的文件当前目录中查找一个.babelrc
文件。 如果不存在,它会向外层目录遍历目录树,直到找到一个.babelrc
文件,或一个package.json
文件中有"babel": {}
。
2.2.1 示例-在2.1例子的基础上删去之前生成的output.js文件,新建一个.babelrc文件写入presets配置,再执行npx babel babel.js -o output.js
2.3 Babel 的插件和 Preset
Babel 的插件分为两类:转换插件和语法解析插件。
转换插件主要职责是进行语法转换的(比如我们要将箭头函数转换为 ES5 函数写法,那么可以单独安装@babel/plugin-transform-arrow-functions插件),而解析插件则是扩展语法的,比如我们要解析jsx
这类 React 设计的特殊语法,则需要对应的 jsx 插件。如果不想一个个的添加插件,那么可以使用插件组合 preset(插件预设,插件组合更加好理解一些),最常见的 preset 是@babel/preset-env
。
@babel/preset-env是 Babel 官方推出的插件预设,它可以根据开发者的配置按需加载对应的插件,通过@babel/preset-env我们可以根据代码执行平台环境和具体浏览器的版本来产出对应的 JavaScript 代码,例如可以设置代码执行在 Node.js 8.9 或者 iOS 12 版本。
2.4 Babel polyfill
Babel 只负责进行语法转换,即将 ES6 语法转换成 ES5 语法,但是如果在 ES5 中,有些对象、方法实际在浏览器中可能是不支持的,例如:Promise
、Array.prototype.includes
,这时候就需要用@babel/polyfill
来做模拟处理。
’@babel/polyfill’实际是core-js和regenerator-runtime的合集。
@babel/polyfill使用方法是先安装依赖,然后在对应的文件内显性的引入:
# 安装,注意因为代码中引入了 polyfill,所以不再是开发依赖(--save-dev,-D)
npm i @babel/polyfill
在文件内直接import
或者require
进来:
// polyfill
import '@babel/polyfill';
console.log([1, 2, 3].includes(1));
babel-polyfill会污染全局,如果做一个独立的web系统则无碍,但做一个三方的库lib就会出问题;babel-runtime不会污染全局环境(_include, _promise这种写法)。
2.5 Bable runtime
@babel/polyfill虽然可以解决模拟浏览器不存在对象方法的事情,但是有以下两个问题:
1)直接修改内置的原型,造成全局污染;
2)无法按需引入,Webpack 打包时,会把所有的 Polyfill 都加载进来,导致产出文件过大。
为了解决这个问题,Babel 社区又提出了@babel/runtime的方案,@babel/runtime不再修改原型,而是采用替换的方式,比如我们用 Promise,使用@babel/polyfill会产生一个window.Promise对象,而@babel/runtime则会生成一个_Promise(示例)来替换掉我们代码中用到的Promise。另外@babel/runtime还支持按需引入。
2.5.1 使用示例:以@babel/runtime转换Object.assign
为例
npm i @babel/runtime # 安装依赖@babel/runtime
npm i -D @babel/plugin-transform-runtime # 安装@babel/plugin-transform-runtime作为 Babel 插件
npm i -D @babel/plugin-transform-object-assign #安装需要转换Object.assign的插件
编写一个runtime.js文件,内容如下:
Object.assign({}, {x: 1})
执行npx babel runtime.js --plugins @babel/plugin-transform-runtime,@babel/plugin-transform-object-assign
最终的输出结果是:
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
(0, _extends2["default"])({}, {
x: 1
});
三、在webpack中使用Babel
babel:JS新语法编译工具,不关心模块化只处理语法;
webpack:打包构建工具,处理模块化,是多个loader、plugin能力的集合;
3.1 示例-在2.1.1例子文件夹的基础上
npm init初始化package.json文件。首先安装 npm 依赖,然后创建webpack.config.js配置文件
# 安装开发依赖
npm i babel-loader @babel/core @babel/preset-env @babel/plugin-transform-runtime -D
npm i webpack webpack-cli -D
# 将 runtime 作为依赖
npm i @babel/runtime -S
可以直接将 Babel 的配置写到webpack配置文件的rules数组use的options中,还可以在项目根目录下创建.babelrc或者使用package.son的 babel 字段。这里我们直接使用2.2.1中创建好的.babelrc文件:
// webpack.config.js
module.exports = {
entry: './babel.js',
mode: 'development',
devtool: false,
module: {
rules: [
{
test: /.js$/,
use: [
{
loader: 'babel-loader'
}
]
}
]
}
};
.babelrc
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage" // 按需加载:usage 表示明确使用到的 Polyfill 引用。在一些 ES2015+ 语法不支持的环境下,每个需要用到 Polyfill 的引用时,会自动加上
}
]
]
}
package.json中加入npm scripts流的webpack命令:
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
+ "build": "webpack --config webpack.config.js"
},
执行npm run build打包:
发现报错,阅读提示发现需要安装core-js
npm install --save core-js@2
然后在npm run build:
代码见:github
本文引用参考:
08 在 Webpack 中使用 Babel 转换 JavaScript 代码-慕课专栏www.imooc.com Babel基本概念coding.imooc.com