浅谈Babel

作者: snow_in | 来源:发表于2018-09-27 11:04 被阅读3次

前几天遇到一个用户反馈说页面打不开的问题,而且还是其中两个页面,其他的都没有问题,于是就要来了账号自己登陆一下看看是哪里报错。奇怪的是我们登陆都好好的啊~~ 这时候用户发来了报错信息:


babel0.png

一想这应该是浏览器兼容问题了,不识别es新的API,于是下载了低版本的Chrome浏览器打开果然报错。

简介

我们知道babel是转译es的,究竟babel哪里没配置对呢?让我们来捋一捋babel

Babel is a JavaScript compiler。这是Babel官网上的简单介绍,就是“Babel是一个JavaScript转译器”,这里有的翻译为编译器,有的翻译为转译器,我觉得转译器比较贴切,因为经过Babel转译后还是JS语言。

我们知道,JS的发展非常迅速,新的语法/特性等层出不穷。但是浏览器的发展速度跟不上JS的发展,新的特性不能及时普及,在得到广泛普及之前,Babel能够让我们提前使用它们。它可以把 ECMAScript 2015+ 代码转换为向后兼容版本的 JavaScript 代码。不过Babel只转译新的语法,JS新增的API和全局对象并不支持。

我们写个简单的例子直观的看一下Babel:


babel1.png

目录就是这样的,我们在package.json的scriptes中添加一条命令,用来转译我们的文件。

如果我们什么都没有配置,Babel并不会起作用,而是会原样输出代码。现在,我们在没有配置Babel的情况下执行命令看一下输出
原文件:


babel2.png

转译之后:


babel3.png
我们发现前后并没有变化
要想Babel起作用,就得告诉他要做什么。自然,我们就得要配置插件啦。

babel转译器

  1. plugins
    用来转译单一功能的插件,像是transform-es2015-classes,就只转译class类。且如果插件以babel-plugin-开头,则可以省略该前缀。
{
  "plugins": [
    "myPlugin", // 等价于
    "babel-plugin-myPlugin"
  ]
}
  1. presets
    转译器,一组插件的集合。人都是有惰性的,让我们一个个地配置plugin岂不是很烦,presets就是帮我们解决这个烦恼的。babel提供了如下的一些preset:
  • es2015
  • es2016
  • es2017
  • env

es20xx的preset只转译该年份批准的标准,而env则代指最新的标准,包括了latest和es20xx各年份

了解了plugins和presets之后,我们就来配置一下Babel吧。我们的例子是用了es6的class类,转译class类的插件就是transform-es2015-classes


babel5.png

现在再执行一下命令:


babel6.jpg
可以看到代码已经被编译了。
如果我们又用到了箭头函数,就要在Babel配置的plugins里面再添加transform-es2015-arrow-functions插件。一个一个配置太繁琐,这时候presets就登场了。
babel7.png

执行命令之后:


babel8.png

可以看到不论是class还是箭头函数都被转译了。

我们看上面转译class的代码,是定义了两个函数_createClass和_classCallCheck,那如果我们在多个文件中都用到了class,岂不是要定义很多遍?现在我们在index.js文件里面也定义一个class,执行命令看一下结果:


image.png

果然跟我们想的一样,那这样不是产生了很多冗余吗??不用担心,我们还有transform-runtime


babel9.png
再执行命令:
babel10.png

可以看到是从babel-runtime引入辅助函数,而不是定义了,这就避免了冗余代码。

babel-runtime是把我们开发中依赖的全局内置函数等提取到公共模块中,在转译代码的时候通过导入模块引入,避免了污染全局作用域。为什么说可以避免污染全局作用域呢?假如我们全局引入了babel-polyfill,我们在项目中由于某种原因自定义了Array.from()方法,那么babel-polyfill中的Array.from()方法就跟我们自定义的产生了冲突。babel-runtime就没有这个问题。

babel-plugin-transform-runtime 插件做了如下事情:

  • core-js:自动导入babel-runtime/core-js,并将全局静态方法、全局内置对象等映射到对应的模块。
  • helper:将内联的工具函数移除,改成通过babel-runtime/helpers模块进行导入,比如_classCallCheck工具函数。
  • regenerator:使用 async/generator 函数时自动导入 babel-runtime/regenerator模块。

可以通过配置来控制开关

{
  "plugins": [
    ["transform-runtime", {
      "corejs": false,
      "helpers": true,
      "regenerator": true,
      "moduleName": "babel-runtime"
    }]
  ]
}

有了transform-runtime怎么还需要babel-polyfill呢?看看官方怎么说的:
NOTE: Instance methods such as "foobar".includes("foo") will not work since that would require modification of existing built-ins (Use babel-polyfill for that).

因为transform-runtime不污染全局变量,所以实例方法无法使用,还得引入babel-polyfill,这就是文章开头说的为什么报错的原因。我们在项目的入口文件加上

import 'babel-polyfill'

就可以正常工作了。

相关文章

  • 浅谈Babel

    前几天遇到一个用户反馈说页面打不开的问题,而且还是其中两个页面,其他的都没有问题,于是就要来了账号自己登陆一下看看...

  • Babel浅谈

    BABEL ES6语法在部分浏览器上,并不支持,而开发人员心里想着尝鲜ES6,鱼与熊掌无法兼得。面对选择:要ES6...

  • babel配置及插件注解

    babel插件 @babel/cli @babel/core @babel/preset-env @babel/p...

  • babel插件入门-AST

    目录 Babel简介 Babel运行原理 AST解析 AST转换 写一个Babel插件 Babel简介 Babel...

  • webpack学习四(babel)

    babel-loader安装 npm i babel-loader @babel/core @babel/pres...

  • webpack4.x + react启用 jsx 语法?

    安装 babel 插件运行cnpm i babel-core babel-loader babel-plugin-...

  • react 使用 jsx语法

    安装 babel 插件 运行cnpm i babel-core babel-loader babel-plugin...

  • react webpack配置

    babel编译jsx babel-loader;webpack调用babel的桥梁@babel/core;babe...

  • babel学习笔记

    babel 转译 安装以下依赖: @babel/core调用 Babel 的 API 进行转码 babel-loa...

  • 2022-01-07 webpack中babel的使用

    安装依赖 @babel/core babel的核心依赖 @babel/preset-env babel的预置环境,...

网友评论

    本文标题:浅谈Babel

    本文链接:https://www.haomeiwen.com/subject/ysadoftx.html