babel7 配置详解

polyfill

  • babel的配置,presets是从右往左执行,plugins相反
  • corejs 是一个给低版本的浏览器提供接口的库,如 Promise, map, set 等
  • babel7的模块以@babel开始
  • babel7已经移除了babel-preset-stage-0这种stage的preset
  • 一个babel的preset是一个可共享的插件包
  • @babel/polyfill 模块包括 core-js 和一个自定义的 regenerator runtime 模块用于模拟完整的 ES2015+ 环境
  • 因为新的api太多了,如果引入全部的polyfill,那就太多了,所以 transform runtime 就是干这个的
  • Babylon 是 Babel 的解析器。最初是 从Acorn项目fork出来

babel-polyfill

  • 通过修改全局方法和原型
  • 如果直接用 @babel/polyfill 3种方式(入口,文件入口,和env的useBuildin),
  • 缺点 会引入多余的代码,但是不用手动配置太多东西,但是会污染全局变量,如果不希望这样

transform-runtime

npm install --save-dev @babel/plugin-transform-runtime
npm install --save @babel/runtime 

  • babel在polyfill一些方法时,默认就加到每个需要这个方法的文件头部,造成大量的代码重复,runtime插件还可以创建一个沙箱环境,避免代码污染,所以在写一些库或者插件应该使用这个
{
  "plugins": [
    [
      "@babel/plugin-transform-runtime",
      {
        "absoluteRuntime": false,
        "corejs": false,
        "helpers": true,
        "regenerator": true,
        "useESModules": false,
        "version": "7.0.0-beta.0"
      }
    ]
  ]
}
// 定义corejs版本重写helper来源库,corejs:2只支持全局变量(例如Promise)和静态属性(例如Array.from),而corejs:3还支持实例属性(例如[].Includes)。 
// 默认不支持提案,如要支持 ['@babel/plugin-transform-runtime', { corejs: 3, proposals: true }]
//corejs 	Install command
//false	npm install --save @babel/runtime
//2		npm install --save @babel/runtime-corejs2
//3		npm install --save @babel/runtime-corejs3

core-js

// polyfill all `core-js` features:
import "core-js";
// polyfill only stable `core-js` features - ES and web standards:
import "core-js/stable";
// polyfill only stable ES features:
import "core-js/es";



babel

  • babel配置
const presets = [
  [
    "@babel/env",
    {
      targets: {
        edge: "17",
        firefox: "60",
        chrome: "67",
        safari: "11.1",
      },
      useBuiltIns: "usage", 
      // 这个配置表示  @babel/preset-env 怎么处理 polyfills 
      // 在使用"@babel/env"这个preset时,有这个配置,就会只加载需要的新语法,就和用了 transform runtime 一样 
      // 当这个值是 usage时, 就不要在webpack入口和文件入口引入有两种下边配置   
      
      1. corejs: {  version: 3,proposals: true},  
      // 这样会开启core-js支持的所有提案 ,默认是2
      // 3 要手动安装  npm install --save core-js@^3 
      
      2. shippedProposals: true                  
      // 如果是true就会开启已经发布的提案
     
      // 如果配置是 entry 就在源代码的第一行 import("babel-polyfill")
      
    },
  ],
];

module.exports = { presets };

  • 同样移除了@babel/polyfill的 proposal语法,现在@babel/polyfill只是 code-js v2.0的别名而已 ,如果需要再使用,要使用引入
// core-js v2

// Stage 3
import "core-js/fn/string/trim-left";
import "core-js/fn/string/trim-right";
import "core-js/fn/string/match-all";
import "core-js/fn/array/flat-map";
import "core-js/fn/array/flatten"; // RENAMED
import "core-js/fn/global";

// Stage 1
import "core-js/fn/symbol/observable";
import "core-js/fn/promise/try";
import "core-js/fn/observable";

// Stage 1 Math Extensions
import "core-js/fn/math/clamp";
import "core-js/fn/math/deg-per-rad";
import "core-js/fn/math/degrees";
import "core-js/fn/math/fscale";
import "core-js/fn/math/iaddh";
import "core-js/fn/math/isubh";
import "core-js/fn/math/imulh";
import "core-js/fn/math/rad-per-deg";
import "core-js/fn/math/radians";
import "core-js/fn/math/scale";
import "core-js/fn/math/umulh";
import "core-js/fn/math/signbit";

// Stage 1 "of and from on collection constructors"
import "core-js/fn/map/of";
import "core-js/fn/set/of";
import "core-js/fn/weak-map/of";
import "core-js/fn/weak-set/of";
import "core-js/fn/map/from";
import "core-js/fn/set/from";
import "core-js/fn/weak-map/from";
import "core-js/fn/weak-set/from";

// Stage 0
import "core-js/fn/string/at";

// Nonstandard
import "core-js/fn/object/define-getter";
import "core-js/fn/object/define-setter";
import "core-js/fn/object/lookup-getter";
import "core-js/fn/object/lookup-setter";
// import "core-js/fn/map/to-json"; // Not available standalone
// import "core-js/fn/set/to-json"; // Not available standalone

import "core-js/fn/system/global";
import "core-js/fn/error/is-error";
import "core-js/fn/asap";

// Decorator metadata? Not sure of stage/proposal
import "core-js/fn/reflect/define-metadata";
import "core-js/fn/reflect/delete-metadata";
import "core-js/fn/reflect/get-metadata";
import "core-js/fn/reflect/get-metadata-keys";
import "core-js/fn/reflect/get-own-metadata";
import "core-js/fn/reflect/get-own-metadata-keys";
import "core-js/fn/reflect/has-metadata";
import "core-js/fn/reflect/has-own-metadata";
import "core-js/fn/reflect/metadata";

  • peerDependencies are dependencies expected to be used by your code,
    as opposed to dependencies only used as an implementation detail.
  • babel插件的名字可以简写
-  "presets": ["@babel/preset-react"],
+  "presets": ["@babel/react"], // this is equivalent

-  "plugins": ["@babel/transform-runtime"],
+  "plugins": ["@babel/plugin-transform-runtime"], // same

  • 插件,没发布的语法,要加proposal
@babel/plugin-transform-function-bind is now @babel/plugin-proposal-function-bind (Stage 0)
@babel/plugin-transform-class-properties is now @babel/plugin-proposal-class-properties (Stage 3)

  • more plugins
// @name @babel/plugin-transform-runtime
A plugin that enables the re-use of Babel's injected helper code to save on codesize

// dev 
npm install --save-dev @babel/plugin-transform-runtime 
// prod 
npm install --save @babel/runtime 


// 解析export default babel6之后,对export default支持不好 
// yarn add -D babel-plugin-add-module-exports
{
  "presets": [["@babel/env", { "modules": "commonjs" }]],
  "plugins": ["add-module-exports"]
}

// @name @babel/plugin-proposal-object-rest-spread
// 对象展开符 {...a}

// @name @babel/plugin-proposal-class-properties
// @eg 类的用法 
class Bork {
  static a = "foo";
}

// @name  ["@babel/plugin-proposal-decorators", { "legacy": true }] 
// 装饰器 

demo config

{
  "presets": [
    [
      "@babel/env",
      {
        "targets": {
          "chrome": "66"
        },
        "corejs": {
          "version": 2
        },
        "useBuiltIns": "usage",
        "modules": "commonjs"
      }
    ],
    "@babel/react"
  ],
  "plugins": [
    [
      "@babel/plugin-proposal-decorators",
      {
        "legacy": true
      }
    ],
    [
      "@babel/plugin-proposal-class-properties",
      {
        "loose": true
      }
    ],
    "add-module-exports",
    [
      "import",
      {
        "libraryName": "antd",
        "libraryDirectory": "es",
        "style": true
      }
    ]
  ]
}

自定义插件

1. 配置插件 
{
  "presets": [
    "@babel/env"
  ],
  "plugins": [
    [
      "@babel/huahua", {"libs" : ["lodash"]}
    ]
  ]
}
2. 写好插件,放到 @babel 目录下
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;

var _helperPluginUtils = require("@babel/helper-plugin-utils");

var _core = require("@babel/core");
var types = require("@babel/types");

var _default = (0, _helperPluginUtils.declare)(api => {
  api.assertVersion(7);
  return {
    name: "huahua",
    visitor: {
      ImportDeclaration(path, ref){
        // 当前节点
        const node = path.node;

        // 配置支持的库
        const libs = ref.opts.libs;

        // 当前的库
        const lib = node.source.value;

        if(libs.indexOf(lib) > -1){
          let vars = node.specifiers;
          if(vars[0].type !== 'ImportDefaultSpecifier'){
            let imports = vars.map(item => {
              return types.ImportDeclaration(
                [types.ImportDefaultSpecifier(item.local)],
                types.StringLiteral( `${node.source.value}/${item.local.name}`)
              )
            })
            path.replaceWithMultiple(imports)
          }
        }
      }
    }
  };
});

exports.default = _default;

babel处理过程

  • parse :词法分析, 词法分析阶段把字符串形式的代码转换为 令牌(tokens) 流 和 语法分析 语法分析阶段会把一个令牌流转换成 AST 的形式
  • transform 转换步骤接收 AST 并对其进行遍历,在此过程中对节点进行添加、更新及移除等操作 @babel/traverse
// 访问器模式遍历树,入和出两个方法,默认就是入 
// 有两个参数 一个是 Path 一个是State
const MyVisitor = {
  Identifier: {
    enter() {
      console.log("Entered!");
    },
    exit() {
      console.log("Exited!");
    }
  }
};
const MyVisitor = {
  Identifier(path ,state){
    // state.opts 就是babelrc配置的选项
  }
};


  • generate 把最终的 AST 转换成字符串形式的代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值