babel polyfill 的一些理解

更新日期: 2019-12-17阅读: 2.4k标签: babel

前言

为了支持业务中少量的es6+的高级特性,最近在研究了一下babel的垫片,现将此整理为文字,如下。

babel 和 babel ployfill 的关系

1、先来理解下 babel 到底是做什么的?

简单来讲,babel解决语法层面的问题。用于将ES6+的高级语法转为ES5。

2、babel polyfill 又是做什么的?

如果要解决api层面的问题,需要使用垫片。比如常见的有babel-polyfill、babel-runtime 和 babel-plugin-transform-runtime。

理清了他们之间的关系,那么再正式来讲讲有关polyfill的二三事。


polyfill 种类

babel polyfill 有三种

* babel-polyfill
* babel-runtime
* babel-plugin-transform-runtime

babel-polyfill

babel-polyfill通过向全局对象和内置对象的prototype上添加方法来实现的。所以这会造成全局空间污染

babel-polyfill使用的两种方式

1、webpack.config.js 中:
配置webpack.config.js里的entry设置为entry: ['babel-polyfill',path.join(__dirname, 'index.js')]

2、业务 js 中:
在webpack.config.js配置的主入口index.js文件的最顶层键入

import 'babel-polyfill'

两者打印出来的大小都是一样的,打包后大小是280KB,如果没有使用babel-polyfill,大小是3.43kb。两则相差大概81.6倍。原因是webpack把babel-polyfill整体全部都打包进去了。而babel-polyfill肯定也实现了所有ES6新API的垫片,文件一定不会小。

那么有没有一种办法,根据实际代码中用到的ES6新增API ,来使用对应的垫片,而不是全部加载进去呢?
是的,有的。那就是 babel-runtime & babel-plugin-transform-runtime,他们可以实现按需加载。

babel-runtime

简单说 babel-runtime 更像是一种按需加载的实现,比如你哪里需要使用 Promise,只要在这个文件头部

import Promise from 'babel-runtime/core-js/promise'

就行了。

不过如果你许多文件都要使用 Promise,难道每个文件都要 import 一下吗?当然不是,Babel 官方已考虑这种情况,只需要使用 babel-plugin-transform-runtime 就可以解决手动 import 的苦恼了。

babel-plugin-transform-runtime

babel-plugin-transform-runtime 装了就不需要装 babel-runtime了,因为前者依赖后者。
总的来说,babel-plugin-transform-runtime 就是可以在我们使用新 API 时 自动 import babel-runtime 里面的 polyfill,具体插件做了以下三件事情:

  • 当我们使用 async/await 时,自动引入 babel-runtime/regenerator
  • 当我们使用 ES6 的静态事件或内置对象时,自动引入 babel-runtime/core-js
  • 移除内联 babel helpers 并替换使用 babel-runtime/helpers 来替换

babel-plugin-transform-runtime 优点:

  • 不会污染全局变量
  • 多次使用只会打包一次
  • 依赖统一按需引入,无重复引入,无多余引入
  • 避免 babel 编译的工具函数在每个模块里重复出现,减小库和工具包的体积

使用方式

在 .babelrc 中配置:

plugins:\["tranform-runtime"\]

打包后大小为 17.4kb,比之前的280kb要小很多。


Plugin 插件

1、官方 Presets

如果不想自己设置一堆插件的话,官方有env,react,flow三个 Presets。即预安装了 plugins 的配置。

presets 属性告诉 Babel 要转换的源码使用了哪些新的语法特性, presets 是一组 Plugins 的集合。如:
babel-preset-es2015: 可以将es6的代码编译成es5
babel-preset-es2016: 可以将es7的代码编译为es6
babel-preset-es2017: 可以将es8的代码编译为es7
babel-preset-latest: 支持现有所有ECMAScript版本的新特性

当我们需要转换es6语法时,可以在 .babelrc 的 plugins 中按需引入一下插件,比如:check-es2015-constants、es2015-arrow-functions、es2015-block-scoped-functions等等几十个不同作用的 plugin。.babelrc 中配置项可能是如下方式:

{
  "plugins": \[
    "check-es2015-constants",
    "es2015-arrow-functions",
    "es2015-block-scoped-functions",
    // ...
  \]
}

但 Babel 团队为了方便,将同属 ES2015 的几十个 Transform Plugins 集合到 babel-preset-es2015 一个 Preset 中,这样我们只需要在 .babelrc 的 presets 加入 ES2015 一个配置就可以完成全部 ES2015 语法的支持了。.babelrc 中配置如下:

{
  "presets": \[
    "es2015"
  \]
}

2、Stage-X(试验性 Presets)

这个比较好理解,就是为了支持 TC39 对于草案阶段的 ES 最新特性而开发的 presets。

  • Stage 0 - 草稿:只是一个设想可能是一个 Babel 插件
  • Stage 1 - 提案:值得去推进的东西
  • Stage 2 - 草案:初始化规范
  • Stage 3 - 候选:完整规范和初始化浏览器实现
  • Stage 4 - 完成:会加入到下一版中

3、转换插件

官方和民间提供了很多的转换插件,用于指定对某一项 ES 高级特性进行转换。
官方见:https://babeljs.io/docs/en/pl...

4、语法插件

这种插件可以让Babel来解析特殊类型的语法。

{
  "parserOpts": {
    "plugins": \["jsx", "flow"\]
  }
}

5、插件开发

见文档:https://github.com/jamiebuild...

开发采用了 AST 抽象语法树,类似于 Eslint 插件开发。

export default function () {
  return {
    visitor: {
      Identifier(path) {
        const name = path.node.name;
        // reverse the name: JavaScript -> tpircSavaJ
        path.node.name = name.split("").reverse().join("");
      }
    }
  };
}

webpack 中使用 babel 二三事

babel 用途是语法转换,所以webpack 中需要用到 babel-loader。而 babel-core 是 Babel 编译器的核心,因此也就意味着如果我们需要使用 babel-loader 进行 es6 转码的话,我们首先需要安装 babel-core。


总结

使用场景建议:

  • 开发应用建议使用 babel-polyfill 会在全局新增对应方法
  • 开发框架建议 babel-plugin-transform-runtime 局部变量 不会污染全局,局部使用es6的函数或方法

原文:https://segmentfault.com/a/1190000021729561

链接: https://www.fly63.com/article/detial/7454

Babel中的stage-0,stage-1,stage-2以及stage-3的作用(转)

大家知道,将ES6代码编译为ES5时,我们常用到Babel这个编译工具。大家参考一些网上的文章或者官方文档,里面常会建议大家在.babelrc中输入如下代码

深入理解Babel原理及其使用,babel把ES6转成ES5的原理是什么?

文的babel使用场景局限于babel配合webpack来转译输出es5的js代码,babel的命令行、以代码形式调用或node环境下这些统统都不会涉及。Babel使用的难点主要在于理解polyfill、runtime和core-js。

ES6之Babel的各种坑总结【转载】

自从 Babel 由版本5升级到版本6后,在安装和使用方式上与之前大相径庭,于是写了这篇入坑须知,以免被新版本所坑。坑一本地安装和全局安装 、坑二编译插件、坑三babel-polyfill插件

babel-preset-env:一个帮你配置babel的preset

babel-preset-env 一个帮你配置babel的preset,根据配置的目标环境自动采用需要的babel插件。babel-preset-env 功能类似 babel-preset-latest,优点是它会根据目标环境选择不支持的新特性来转译

babel-polyfill使用与性能优化

本文主要内容包括:什么是babel-polyfill,如何使用,如何通过按需加载进行性能优化。babel只负责语法转换,比如将ES6的语法转换成ES5。但如果有些对象、方法,浏览器本身不支持,此时需要引入babel-polyfill来模拟实现这些对象、方法。

babel的初步了解

由于现在前端出现了很多非es5的语法,如jsx,.vue,ts等等的格式和写法。babel其实是一个解释器,它主要讲进行中的代码分为三个阶段执行:解释,转换,生成。

深入类和继承内部原理+Babel和 TypeScript 之间转换

在 JavaScript 中,没有基本类型,创建的所有东西都是对象。例如,创建一个新字符串,与其他语言不同,在 JavaScript 中,字符串或数字的声明会自动创建一个封装值的对象,并提供不同的方法,甚至可以在基本类型上执行这些方法。

使用 Webpack 与 Babel 配置 ES6 开发环境

在项目根目录下新建一个配置文件—— webpack.config.js 文件:执行编译打包命令,完成后打开 bundle.js 文件发现 isNull 和 unique 两个函数没有被编译,和 webpack 官方说法一致:webpack 默认支持 ES6 模块语法,要编译 ES6 代码依然需要 babel 编译器。

Babel_如何写一个Babel插件

Babel对代码进行转换,会将JS代码转换为AST抽象语法树(解析),对树进行静态分析(转换),然后再将语法树转换为JS代码(生成)。每一层树被称为节点。每一层节点都会有type属性,用来描述节点的类型。其他属性用来进一步描述节点的类型。

初学 Babel 工作原理

Babel 对于前端开发者来说应该是很熟悉了,日常开发中基本上是离不开它的。我们已经能够熟练地使用 es2015+ 的语法。但是对于浏览器来说,可能和它们还不够熟悉,我们得让浏览器理解它们,这就需要 Babel

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!