webpack学习之6.Babel 7

介绍

Babel用于将ES6+转换为ES5。

Babel本身不具有任何转换功能,它把转换的功能分解到一个个插件中。如果不配置插件,使用babel命令转换的代码并没有什么变化。

Babel转换ES6或其他规范可能需要十几二十个插件,为了使开发者不需要一个个添加安装配置,Babel提供了几组插件的集合,称为预设(preset)。开发者可以直接使用预设。

例如推荐的预设 env(@babel/preset-env),此预设将包含所有支持现代JavaScript的插件(ES6 ES7等)。

预设可以通过配置文件配置。

配置

Babel 有两种并行的配置文件方式,可以一起使用,也可以单独使用,

  • 项目范围的配置
    • babel.config.json 及其他扩展babel.config.[js/cjs/mjs]
  • 相对文件配置
    • .babelrc.json 及其他扩展babel.config.[js/cjs/mjs]。由于兼容原因,.babelrc 相当于 .babelrc.json
    • package.json中的babel选项
 // json 文件
{
  "presets": [...],
  "plugins": [...]
}
// js文件
module.exports = function (api) {
  api.cache(true);

  const presets = [ ... ];
  const plugins = [ ... ];

  return {
    presets,
    plugins
  };
}
// package.json文件
{
  "name": "my-package",
  "version": "1.0.0",
  "babel": {
    "presets": [ ... ],
    "plugins": [ ... ],
  }
}

示例

安装

npm install -D @babel/core @babel/cli @babel/preset-env

创建目录和文件

// babel.config.json
{
    "presets": [
        [
            "@babel/preset-env", // 指定预设
            {
                "targets": {
                    "ie": "8" // 指定目标环境
                }
            }
        ]
    ]
}
// src/util.js
// 语法:箭头函数
const a = () => {
    throw new Error('my name is a')
};

// 内置函数:Promise
let b = new Promise(function(resolve,reject){
    resolve();
});

// 全局方法:includes
let c = [1,2,3].includes(1);

终端运行

npx babel src/util.js --out-dir dist

查看结果,箭头函数已被转换

// dist/util.js
"use strict";
// 语法:箭头函数
var a = function a() {
  throw new Error('my name is a');
};

// 内置函数:Promise
var b = new Promise(function (resolve, reject) {
  resolve();
});

// 全局方法:includes
var c = [1, 2, 3].includes(1);

polyfill

上例转换结果发现,Promise和includes没有被转换。

@babel/polyfill

Babel默认只转换语法,而不转换新的API(内置函数),例如Iterator Set Map Proxy Promise Weakmap Array.from Object.assign includes等全局对象和定义在全局对象上的新方法。

Babel提供一个polyfill(@babel/polyfill),它是个代码块,它通过改变全局(将所有方法都加到原型链上)来兼容新API。
它需要在使用API前引入(import)。或在webpack 的 入口 entry中优先添加@babel/polyfill的入口。

@babel/polyfill由core-js2和regenerator-runtime组成。

安装

npm install --save @babel/polyfill

本例polyfill作为生产环境的依赖(require),所以使用--save安装。

// src/util.js
import '@babel/polyfill';

// 语法:箭头函数
const a = () => {
    throw new Error('my name is a')
};

// 内置函数:Promise
let b = new Promise(function(resolve,reject){
    resolve();
});

// 全局方法:includes
let c = [1,2,3].includes(1);

转换结果:

// dist/util.js
require("@babel/polyfill");

// 语法:箭头函数
var a = function a() {
  throw new Error('my name is a');
};

// 内置函数:Promise
var b = new Promise(function (resolve, reject) {
  resolve();
});

// 全局方法:includes
var c = [1, 2, 3].includes(1);

@babel/polyfill集成了core-js和regenerator:
core-js:转换一些内置类 promises, symbols, collections, iterators, typed arrays等。可以仅加载必需的功能。
regenerator:作为core-js的补充。

@babel/polyfill有两个缺点:
1.导致打包生成的文件很大,因为它是一整个代码代码块。当只使用部分API时,其他的也会被包含进去。这个问题可以通过单独加载core-js的某个功能来解决。
2.污染全局变量,给很多类的原型链都作了修改。

@babel/plugin-transform-runtime & @babel/runtime

上面两个问题主要在于polyfill的引入是内联的,直接插入了一行代码从而无法优化。
babel提供了插件transform-runtime,使每个文件里不用重复定义polyfill,而改为直接从core-js自动引入对应的方法。

core-js@2 仅支持全局变量(例如Promise)和静态属性(例如Array.from)
core-js@3 增加支持实例属性(例如[].includes)

@babel/plugin-transform-runtime 默认不使用core-js ,需要配置corejs指定core-js版本。

安装
本例@babel/runtime作为生产环境的依赖(require),所以使用--save安装。

npm install --save-dev @babel/plugin-transform-runtime
npm install --save @babel/runtime core-js@3

使用插件 指定core-js版本

// babel.config.json
{
    "presets": [
        [
            "@babel/preset-env",
            {
                "targets": {
                    "ie": "8"
                }
            }
        ]
    ],
    "plugins": [
        [
           "@babel/plugin-transform-runtime",
            {
                "corejs": 3
            }
        ]
    ]
}
// src/util.js
// import '@babel/polyfill'; // 不用手动引入
// 语法:箭头函数
const a = () => {
    throw new Error('my name is a')
};

// 内置函数:Promise
let b = new Promise(function(resolve,reject){
    resolve();
});

// 全局方法:includes
let c = [1,2,3].includes(1);

转换结果: Promise和includes改为引用模块中的方法

// dist/util.js
"use strict";
var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");

var _includes = _interopRequireDefault(require("@babel/runtime-corejs3/core-js/instance/includes"));

var _promise = _interopRequireDefault(require("@babel/runtime-corejs3/core-js/promise"));

// 语法:箭头函数
var a = function a() {
  throw new Error('my name is a');
};

// 内置函数:Promise
var b = new _promise["default"](function (resolve, reject) {
  resolve();
});

// 全局方法:includes
var c = (0, _includes["default"])(_context = [1, 2, 3]).call(_context, 1);

代替它们更方便配置polyfill的方式是声明 useBuiltIns。

useBuiltIns

Babel推荐使用的预设 @babel/preset-env 可以根据指定目标环境判断需要做哪些编译。它也支持针对指定目标环境选择需要的polyfill。

@babel/polyfill不支持core-js 2和3 的平滑过渡,Babel 7建议启用core-js3代替使用@babel/polyfill。

如此配置 (“corejs”: { “version”: 3, “proposals”: true }) 而不是 (“corejs”: 3)。需要升级core-js版本为3。

在配置中声明 useBuiltIns ,Babel就会自动引入所需的polyfill,而不需要手动引入@babel/polyfill。

安装

npm install --save-dev @babel/cli @babel/core @babel/preset-env core-js@3

配置

// babel.config.json
{
    "presets": [
        [
            "@babel/preset-env",
            {
                "targets": {
                    "ie": "8"
                },
                "useBuiltIns": "usage",
                "corejs": 3
            }
        ]
    ]
}
// src/util.js
"use strict";
require("core-js/modules/es.array.includes");

require("core-js/modules/es.object.to-string");

require("core-js/modules/es.promise");

// 语法:箭头函数
var a = function a() {
  throw new Error('my name is a');
};

// 内置函数:Promise
var b = new Promise(function (resolve, reject) {
  resolve();
});

// 全局方法:includes
var c = [1, 2, 3].includes(1);

babel-loader

安装

npm install -D babel-loader
// webpack.config.js
module.exports = {
	//...
	module:{
		rules: [
			{
				test: /\/.js$/,
				exclude: /node_modules/,
                use: [
                    {
                        loader: 'babel-loader'
                    }
                ]
			}
		]
	}
}

其他

Babel 7 中 @babel/preset-env 同 @babel/env 在配置中和安装依赖效果一样

参考

一口(很长的)气了解 babel
21 分钟精通前端 Polyfill 方案

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值