分类
默认

webpack 之 babel 使用

babel 前端开发环境必备工具

环境搭建 & 基本配置

  • 环境搭建
  • .babelrc 配置 presets 和 pluins

1、环境配置文件 package.json

{
  "name": "09-babel-demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/cli": "^7.7.5",
    "@babel/core": "^7.7.5",
    "@babel/plugin-transform-runtime": "^7.7.5",
    "@babel/preset-env": "^7.7.5"
  },
  "dependencies": {
    "@babel/polyfill": "^7.7.0",
    "@babel/runtime": "^7.7.5"
  }
}

babel 配置文件 .babelrc

  • presets – 可以作为 Babel 插件的组合
  • pluins
{
    "presets": [
        [
            "@babel/preset-env",
            {
                "useBuiltIns": "usage",
                "corejs": 3
            }
        ]
    ],
    "plugins": [
        [
            "@babel/plugin-transform-runtime",
            {
                "absoluteRuntime": false,
                "corejs": 3,
                "helpers": true,
                "regenerator": true,
                "useESModules": false
            }
        ]
    ]
}

测试 index.js 中的 ES6 代码

const sum = (a, b) => a + b

执行命令 npx babel src/index.js,输出 ES5 语法

var sum = function sum(a, b) {
  return a + b;
};

2、babel-polyfill

1)polyfill 意为补丁,比如

if(!Array.prototype.indexOf){
    Array.prototype.indexOf = (function(Object,max,min){})
}

通过这种方式实现 polyfill

2)core-js 和 regenerator

core-js 是 ES6+ 转 ES5 标准版,github 地址:https://github.com/zloirock/core-js,但 core-js 无法满足 ES6 中 generator,如

// ES6 generator 函数(处理异步),被 async/await 代替
function* tell(){
    console.log('执行 a 处理');
    yield 'a';
    console.log('执行 b 处理');
    yield 'b';
    console.log('执行 c 处理');
    yield 'c';
}
let k = tell();
console.log(k.next());
console.log(k.next());
console.log(k.next());
console.log(k.next());

所以还需要 regenerator 的支持,github 地址:https://github.com/facebook/regenerator

3) babel-polyfill 即是 core-js 和 regenerator 的集合

  • Babel 7.4 之后弃用 babel-polyfill
  • 推荐直接使用 core-js 和 regenerator,但是 babel-polyfill 还是很多人用

babel 只将 ES6+ 语法转 ES5 语法,但不能处理新的 API (新的 API 语法符合 ES5 规范,但浏览器是否兼容,babel 不关心),所以在代码中引入 babel-polyfill

import '@babel/polyfill'
// 新的 API
Promise.resolve(100).then(data => data);
// 新的 API
[10, 20, 30].includes(20)

以上被解析为

require(‘@babel/polyfill’)

// 新的 API

Promise.resolve(100).then(data => data);

// 新的 API

[10, 20, 30].includes(20)

babel 把 import 引入的解析为 require 的模块化,但 babel 不处理模块化,所以还是需要 webpack 配合,然而 babel-polyfill 文件较大,所以应配置 .babelrc 按需引入

注,import ‘@babel/polyfill’ 就不需要手动引入了

{
    "presets": [
        [
            "@babel/preset-env",
            {
                "useBuiltIns": "usage",
                "corejs": 3
            }
        ]
    ],
}

3、babel-runtime

babel-polyfill 的问题

// 污染全局环境
window.Promise = function() {}
Array.prototype.includes = function () {}
// 使用方
window.Promise = 'abc'
Array.prototype.includes = 100
  • 污染全局环境
  • 做独立的 web 系统没关系;如果做第三方 lib 就会有问题

那怎么解决勒,可以换一个名字,如

window.Promise2 = function() {}
Array.prototype.includes2 = function () {}

使用 babel-runtime 就是解决污染环境问题,安装 @babel/plugin-transform-runtime 和 @babel/runtime,参考最上的 package.json 文件,然后默认配置 .babelrc 即可

{
    "plugins": [
        [
            "@babel/plugin-transform-runtime",
            {
                "absoluteRuntime": false,
                "corejs": 3,
                "helpers": true,
                "regenerator": true,
                "useESModules": false
            }
        ]
    ]
}

执行命令 npx babel src/index.js 查看

"use strict";
var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");
require("core-js/modules/es.object.to-string.js");
require("core-js/modules/es.promise.js");
var _includes = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/includes"));
var _promise = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/promise"));
var _context;
var sum = function sum(a, b) {
  return a + b;
}; // 新的 API
_promise["default"].resolve(100).then(function (data) {
  return data;
}); // 新的 API
(0, _includes["default"])(_context = [10, 20, 30]).call(_context, 20);

以上解析后,不会污染全局环境