在现代 Web 应用中,为了让代码能在生产环境高性能的运营,源代码往往需要被编译打包,进行死码删除,代码转换等处理。
babel 和 Typescript 是目前最常用的两个编译器,本文主要讨论两者的区别,帮助你为项目选择最佳工具。
Babel 是一个 JS 编译器,能将现代 ES6+ 语法和特性转换为向后兼容语法,以便能够运行在当前和旧版本的浏览器或其他环境中。拥有语法转换,Polyfill,源码转换等能力,
TS 是目前最常用的编程语言之一,是加了类型系统的 JS,能够帮助在开发时规避一些错误。
TS 有自己的编译器,可将 .ts 文件转换为 .js 文件,然后运行在浏览器、Node.js 等任何能运行 JS 的环境中。
虽然同为编译器,但也有一些区别。
TS 在编译时可以对代码进行类型检查,而 Babel 不支持类型检查。
可以使用 tsc -- noEmit 单独进行 TS 类型检查
Babel 和 TS 两者都只是编译器,真正完成 api polyfill 的是 core-js 。
core-js 是一套模块化的 JS 标准库,提供了 polyfill 的核心实现。
Babel 的 @babel/polyfill 模块包含了 core-js 和 regenerator-runtime 来模拟完整的 ES2015+ 环境。因此可以说 Babel 自带了 polyfill。
regenerator-runtime 是 generator 以及 async/await 的运行时依赖。
而 TS 只能通过 tsconfig 的 target
控制编译为对应 ECMAScript 版本的语法。比如 const/let 变 var,箭头函数变 function,async+await 变
Promise.then 这些,不会引入内置对象的扩展,比如你要运行的浏览器不支持 Promise,编译后也不会带一个完整的 Promise
polyfill,想 polyfill 还是得配合 core-js 。
Babel 是自定义代码转换的不二之选,而且社区生态丰富,有各种各样的插件可以优化你的代码。
而 TS 只支持自己的 Transformer API ,生态远远比不上 Babel 插件,知道的人也比较少,能力也更少。
随着 TS 和 ES6 里引入了类,装饰器提案 proposal-decorators 诞生了,是我们最熟悉的老朋友。但是此装饰器非彼装饰器,历时多年来该提案已经走到了第三版,仍然卡在 stage-2。
首先我们需要知道,JS 与 TS 中的装饰器不是一回事,JS 中的装饰器目前依然停留在 stage-2 阶段,并且目前版本的草案与 TS 中的实现差异相当之大( TS 是基于第一版,JS 目前已经第三版了 ),所以二者最终的装饰器实现必然有非常大的差异。
其次,装饰器不是
TS 所提供的特性(如类型、接口),而是 TS 实现的 ECMAScript 提案(就像类的私有成员一样)。TS 实际上只会对 stage-3
以上的语言特性提供支持,但因为一些原因,当 TS 引入装饰器时,JS 中的装饰器依然处于 stage-1 阶段。 TS 的装饰器其实是 JS 装饰器提案的第一版 。
Babel 编译装饰器需要使用 @babel/plugin-proposal-decorators 插件,通过 version 字段分别支持三版提案:
Babel 默认按第二版进行编译,如果要与 TS 编译行为一致(也就是第一版),需要传入 "version": "legacy" 。
从上面装饰器的例子还可以看出,TS 只会对 stage-3 以上的语言特性提供支持,不支持还在草案阶段的特性。
而 Babel 的 preset-env 支持所有标准特性,还能通过各种 @babel/plugin-proposal-<语言特性> 插件来支持更多还未进入标准的特性。
在性能上,两者差别不大。这里大家可能会有疑问:“Babel 少了类型检查的步骤,编译速度应该会比 TS 快才对啊”。
根据 swc-node 文档的 benchmark 我们可以看到, 在关闭类型检查的情况下,TS 的编译速度是比 Babel 快的 。
esbuild x 510 ops/sec ±1.28% (88 runs sampled)
@swc-node/core x 438 ops/sec ±1.00% (88 runs sampled)
typescript x 28.83 ops/sec ±10.20% (52 runs sampled)
babel x 24.21 ops/sec ±10.66% (46 runs sampled)
Transform rxjs/AjaxObservable.ts benchmark bench suite: Fastest is esbuild
而且还可以借助第三方插件 fork-ts-checker-webpack-plugin 来提速类型检查过程(放到单独的进程中),所以两者的整体性能其实相差不大。
因为 TS 无法自动 polyfill,借助了 core-js 也无法做到按需 polyfill。
而配置 Babel 的 @babel/preset-env 插件:
useBuiltIns: "usage"
targets: <需要兼容的浏览器>
可以根据编译目标和项目的 API 使用情况来精准添加 polyfill,这会大大降低包的体积。
使用 useBuiltIns: "usage" 会在全局添加 polyfill,这会污染全局环境。可以使用 @babel/plugin-transform-runtime 插件为库的代码提供一个沙盒环境,把 polyfill 变成模块化的引入,代码重用的同时避免全局污染。
综上,两者都有各自的编译处理方式,整体看下来,Babel 唯一的缺点就是没有类型检查,但可以使用 tsc --noEmit 单独检查类型。
因此,如果项目中:
以上文章来源于小李的前端小屋 ,作者Leecason
大家知道,将ES6代码编译为ES5时,我们常用到Babel这个编译工具。大家参考一些网上的文章或者官方文档,里面常会建议大家在.babelrc中输入如下代码
文的babel使用场景局限于babel配合webpack来转译输出es5的js代码,babel的命令行、以代码形式调用或node环境下这些统统都不会涉及。Babel使用的难点主要在于理解polyfill、runtime和core-js。
自从 Babel 由版本5升级到版本6后,在安装和使用方式上与之前大相径庭,于是写了这篇入坑须知,以免被新版本所坑。坑一本地安装和全局安装 、坑二编译插件、坑三babel-polyfill插件
babel-preset-env 一个帮你配置babel的preset,根据配置的目标环境自动采用需要的babel插件。babel-preset-env 功能类似 babel-preset-latest,优点是它会根据目标环境选择不支持的新特性来转译
本文主要内容包括:什么是babel-polyfill,如何使用,如何通过按需加载进行性能优化。babel只负责语法转换,比如将ES6的语法转换成ES5。但如果有些对象、方法,浏览器本身不支持,此时需要引入babel-polyfill来模拟实现这些对象、方法。
由于现在前端出现了很多非es5的语法,如jsx,.vue,ts等等的格式和写法。babel其实是一个解释器,它主要讲进行中的代码分为三个阶段执行:解释,转换,生成。
在 JavaScript 中,没有基本类型,创建的所有东西都是对象。例如,创建一个新字符串,与其他语言不同,在 JavaScript 中,字符串或数字的声明会自动创建一个封装值的对象,并提供不同的方法,甚至可以在基本类型上执行这些方法。
在项目根目录下新建一个配置文件—— webpack.config.js 文件:执行编译打包命令,完成后打开 bundle.js 文件发现 isNull 和 unique 两个函数没有被编译,和 webpack 官方说法一致:webpack 默认支持 ES6 模块语法,要编译 ES6 代码依然需要 babel 编译器。
Babel对代码进行转换,会将JS代码转换为AST抽象语法树(解析),对树进行静态分析(转换),然后再将语法树转换为JS代码(生成)。每一层树被称为节点。每一层节点都会有type属性,用来描述节点的类型。其他属性用来进一步描述节点的类型。
Babel 对于前端开发者来说应该是很熟悉了,日常开发中基本上是离不开它的。我们已经能够熟练地使用 es2015+ 的语法。但是对于浏览器来说,可能和它们还不够熟悉,我们得让浏览器理解它们,这就需要 Babel
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!