前些天使用了 babel7
,特来做个笔记。原文发布在GitHub。
presets
在 babel7
中,已经废弃了之前的阶段性提案,现在统一使用 @babel/preset-env
。所以呢,这里倒是省去了一些麻烦。在 webpack
配置中 preset-env
配合 babel-loader
就可以转换 ES2015+
语法了。同时,官方建议我们使用 targets
设定目标浏览器决定需要兼容的功能。举个例子:
module.exports = {
presets: [
[
'@babel/preset-env',
{
targets: {
ie: "11"
}
}
]
]
}
polyfill
polyfill
在之前都是用来引入新的 api
和功能的。如我们常用的 promise
,Object.assign
等。在 babel6
及之前,只需要在入口引入 polyfill
即可。然而这也带来了问题,一次性加载了整个 polyfill
,十分冗余。 而用了 babel7
通过简单的配置就可以达成按需加载的目的,我们也不再需要手动引入 polyfill
。
useBuiltIns
没错,使用这个新的配置项,就可以实现按需加载 polyfill
。其值可取以下3个:
false
值为 false
的时候,相当于没用,这时就得手动引入所有的 polyfill
。
entry
使用 entry
的时候,也需要手动引入 polyfill
,即 import '@babel/polyfill';
,同时也引入了所有的 polyfill
。这个配置项,总觉得没什么用,如果有老哥知道的话可以在评论区提出一起讨论。
usage
值为 usage
的时候,无需引入 polyfill
,babel
会自动按需加载需要的功能:
{
\\...
useBuiltIns: 'usage'
}
如果需要在命令行打印加载项,可以设置 debug
:
{
\\...
useBuiltIns: 'usage',
dubug: true
}
plugin-transform-runtime
例如使用 class(类)
的时候,babel
会在这前面添加一个帮助函数。如下所示:
源代码:
// source code
class Test {}
编译后:
"use strict";
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Test = function Test() {
_classCallCheck(this, Test);
};
可以看到,在编译输出的代码里,helper
函数被直接嵌入代码中。如果你只有这一个 js
文件用到了这个 helper
,那这样并没有问题。但试想一下,如果你有很多个脚本文件,每一个你都用到了 class
,babel
可不管你这么多,每个编译后的文件都包含一个一模一样的 helper
函数,便造成了冗余。所幸,我们可以使用 @babel/plugin-transform-runtime
和 @babel/runtime
来解决这个问题。添加如下配置:
plugins: [
'@babel/plugin-transform-runtime'
]
此时再编译上面的代码,得到的结果如下:
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var Test = function Test() {
(0, _classCallCheck2.default)(this, Test);
};
此时不再是直接把 helper
函数嵌入代码中,而是使用 require
加载公共 helper
。
使用 polyfill
还是 runtime
- 对于要发布给别人使用的工具和库来说,使用
@babel/runtime
比较合适。因为@babel/polyfill
会污染全局环境,别人引入你的库可能会造成不必要的污染。 - 而
@babel/runtime
不能提供一些实例方法,诸如"foobar".includes("foo")
这类的。还需自己手动引入。
对于自己的应用项目,还是引入 @babel/polyfill
更好,提供的功能更全面,也不需要担心全局污染。但如我上面所说的,一些 helper
函数,如果不使用 @babel/plugin-transform-runtime
插件的话,会引入冗余的代码。而这两者放在一起使用的时候,如果没有对 plugin-transform-runtime
进行配置,是不会有重复功能的引入的。
总结
上面说了这么多,现在给出 babel7
和 webpack
的实践作为结束。
1.添加依赖
cnpm i --save-dev babel-loader @babel/core @babel/preset-env @babel/plugin-transform-runtime
// &
cnpm i --save @babel/polyfill @babel/runtime
2.webpack
配置
module.exports = {
// ...
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
}
]
}
};
3.babel
配置
以下是在自己的应用项目中的配置:
// babel.config.js
module.exports = {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
targets: {
ie: 10 // 根据自己的目标环境进行配置
},
debug: true,
// corejs这一项也需要加上,corejs有2和3两个版本
// 如果不确定有没有下载core-js,可执行 cnpm i core-js@2 --save
corejs: 2
}
]
],
plugins: [
'@babel/plugin-transform-runtime'
]
};
发布给别人使用的工具或库,可以使用以下配置:
// babel.config.js
module.exports = {
presets: [
'@babel/preset-env'
],
plugins: [
[
'@babel/plugin-transform-runtime',
{
corejs: 2
// ...
}
]
]
};
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。