Open brunoyang opened 8 years ago
Up!
cool
请问一下作者,babel-runtime不污染全局,用到什么需要polyfill的api需要手动引入,比如promise;而babel-plugin-transform-runtime引入后,还是会用到什么api需要单独手动引入么???
若是这样,这样开发时岂不是很繁琐?
@wonyun 首先感谢回复。行文上可能有疏漏引起误解。因为 babel-runtime 都是自动帮你引入所需 polyfill,但每个文件引入的都是全量的 polyfill,很容易引起体积暴涨。所以我们可以加上 babel-plugin-transform-runtime,这样 runtime 所用的 polyfill 就会从 transform-runtime 里引入,就避免了体积暴涨的问题。
@brunoyang ,不太明白这句因为 babel-runtime 都是自动帮你引入所需 polyfill
,比方说我在代码中用到了Promise,在IE8下,babel-runtime难道会自动的帮我require这个promise的polyfill,还是需要开发者在代码开头手动引入这个promise polyfill文件?
@wonyun 应该这么说,Babel 中 runtime 只是个 helper 函数库,runtime transform 根据 ast 结果帮你引入所需 helper 函数。所以是只用 runtime 是需要手动,但不要这样用,而是用 runtime transform。
@brunoyang ,非常感谢,理解其中情况,babel-runtime是会自动引入polyfill的
博主,问下transform-runtime
,transform-decorators-legacy
,transform-class-properties
这些plugins引入的数组顺序会有关系吗
好文,顶
@wonyun 没明白意思
非常感谢,理解其中情况,babel-runtime是会自动引入polyfill的
这句话中babel-plugin-runtime-transform 是自动的吧?所有的helper,一个bundle里面就一个;而babel-runtime,一个模块(文件)里一个,打包成bundle就有好多冗余的代码了。
@lcoder 对,一个bundle里面一个但不用太在意,这些helper的体积很小,用这些helper换来的是自动引入polyfill的开发体验
那问问作者,babel-plugin-runtime-transform,引入的模块,需要手动安装并在.babelrc添加plugins或presets么?
现在引入了runtime-transform,但是发现array中的fill不起作用,然后又去引用了polyfill,是在webpack中引入的,但是发现都不起作用
好文章!顶顶
写得不错
写的不错,顶
请问作者, es2015 跟 stage-* 是不是得同时存在, 如果自己写的代码存在es6、7语法的话
是不是说transform-runtime有两个作用:
如果只用babel-runtime,那么如果多个模块都引用了helper,那么这些模块中都会有这些helper。如果用了transform-runtime,会将重复的helper提取出来让所有的模块重用
如果只用babel-runtime,需要通过类似const Promise = require('babel-runtime/core-js/promise')这样的方式手动引入。而如果用了transform-runtime就不用管了,需要用到的地方会自动引入
这样的理解对吗?
@wonyun @brunoyang
还有一个疑问就是,babel-polyfill和babel-runtime + transform-runtime这两种方案是不是有以下区别:
babel-polyfill的方案会把所有的都打包进来
babel-runtime + transform-runtime 的方案只会把那些用到的helper提取打包进来,而那些没用到的则不会。
那么这样的话babel-runtime + transform-runtime会比babel-polyfill的方案更省空间。
这样的理解对吗?
@wonyun @brunoyang
@xiaozhouwu babel-runtime 是会自动引入 polyfill 每一个模块 都有 ransform-runtime 的方案只会把那些用到的重复helper过滤掉 打包。 babel-polyfill 应该是全局的
有点疑惑想请教,transform-runtime中的"helpers"和"moduleName"到底设置了什么,我是用webpack打包的,感觉没什么影响,官网上的解释也不是很理解
@xiaozhouwu
babel-polyfill
内部实现包含了所有的polyfill
,而且部分polyfill
是通过改变全局对象的方式。使用的方式也是直接在你的入口文件中去引入babel-polyfill
。
babel-runtime
及其插件babel-plugin-transform-runtime
,会在babel
对你的代码编译的过程中,分析你的代码,如果用到了一些新的API
,需要引入polyfill
的代码,会自动帮你引入在core-js
或者regenerator.js
中的shim代码。babel-plugin-transform-runtime
这个插件主要是做了一层映射,映射到babel-runtime
内引用的core-js
或regenerator.js
中具体对应的helper
:
如果你使用了一些新的实例上的方法,例如:
const str = [1, 2, 3]
str.includes(2)
像这种实例上添加的新的方法,仅仅用core-js中的shim是没法解决的。这个时候必须要引入babel-polyfill
。
babel-runtime
及其插件babel-plugin-transform-runtime
事实上就是按需去引入你需要的helper
,而babel-polyfill
是全部引入进去,从某种程度上说,确实比全部引入babel-polyfill
最终打出的包更小。
"上面提到的插件可以将语法从 es6 转成 es5,但没有提供 api 的转码功能,如 Promise、..." 不太对吧, 比如babel-plugin-transform-object-assign属于 babel-plugin-*可以转换Object.assign
15 年 11 月,Babel 发布了 6.0 版本。相较于前一代 Babel 5,新一代 Babel 更加模块化, 将所有的转码功能以插件的形式分离出去,默认只提供 babel-core。原本只需要装一个 babel ,现在必须按照自己的需求配置,灵活性提高的同时也提高了使用者的学习成本。下面就来讲讲 Babel 全家桶中的各个部分。
npm i babel
已经弃用,你能下载到的仅仅是一段 console.warn,告诉你 babel 6 不再以大杂烩的形式提供转码功能了。
npm i babel-core
babel-core 的作用是把 js 代码分析成 ast ,方便各个插件分析语法进行相应的处理。有些新语法在低版本 js 中是不存在的,如箭头函数,rest 参数,函数默认值等,这种语言层面的不兼容只能通过将代码转为 ast,分析其语法后再转为低版本 js。
npm i babel-register
该模块给 require 加了个钩子,
.js
、jsx
、.es
、es6
后缀的模块都会先转码。此外有几点需要注意:babel-register
;npm i babel-cli -g
babel 命令行工具,可以转码文件或目录并输出至指定文件,直接看用法:
npm i babel-plugin-*
babel-plugin-* 代表了一系列的转码插件,如
babel-plugin-transform-es2015-arrow-functions
用于转码 es6 中的箭头函数,babel-plugin-transform-async-to-generator
用于将 es7 中的 async 转成 generator。在
.babelrc
中的配置:npm i babel-preset-*
我们现在有了
babel-plugin
系列,可以按需配置自己想要的特性。但若是想搭个 es6 环境,一个个地配置各个插件,我猜你会疯掉。babel-preset
系列就可以满足我们的需求,babel-preset
系列打包了一组插件,类似于餐厅的套餐。如babel-preset-es2015
打包了 es6 的特性,babel-preset-stage-0
打包处于 strawman 阶段的语法(关于 ECMAScript 制定流程可以看这里),.babelrc
中可以这样配置:npm i babel-runtime / babel-polyfill
上面提到的插件可以将语法从 es6 转成 es5,但没有提供 api 的转码功能,如 Promise、Set、Map 等新增对象,Object.assign、Object.entries 等全局对象上的新增方法都不会转码。而
babel-runtime
和babel-polyfill
就是为此而生。这两个模块功能几乎相同,就是转码新增 api,模拟 es6 环境,但实现方法完全不同。babel-polyfill 的做法是将全局对象通通污染一遍,比如想在 node 0.10 上用 Promise,调用 babel-polyfill 就会往 global 对象挂上 Promise 对象。对于普通的业务代码没有关系,但如果用在模块上就有问题了,会把模块使用者的环境污染掉。
babel-runtime
的做法是自己手动引入 helper 函数,还是上面的例子,const Promise = require('babel-runtime/core-js/promise')
就可以引入 Promise。但 babel-runtime 也有问题,第一,很不方便,第二,在代码中中直接引入 helper 函数,意味着不能共享,造成最终打包出来的文件里有很多重复的 helper 代码。所以,babel 又开发了
babel-plugin-transform-runtime
,这个模块会将我们的代码重写,如将 Promise 重写成 _Promise(只是打比方),然后引入_Promise
helper 函数。这样就避免了重复打包代码和手动引入模块的痛苦。此外,babel-runtime
不能转码实例方法,比如这样的代码:这只能通过
babel-polyfill
来转码,因为babel-polyfill
是直接在原型链上增加方法。babel-polyfill vs babel-runtime
那什么时候用
babel-polyfill
什么时候用babel-runtime
呢?如果你不介意污染全局变量(如上面提到的业务代码),放心大胆地用babel-polyfill
;而如果你在写模块,为了避免污染使用者的环境,没的选,只能用babel-runtime
+babel-plugin-transform-runtime
。和 webpack 配合
很少有大型项目仅仅需要 babel,一般都是 babel 配合着 webpack 或 glup 等编译工具一起上的。下面就来介绍下 babel 和 webpack 如何 1 + 1 > 2。
为了显出 babel 的能耐,我们分别配个用
babel-polyfill
和babel-runtime
、支持 react 的webpack.config.js先来配使用
babel-runtime
的:需要注意的是,
babel-runtime
虽然没有出现在配置里,但仍然需要安装,因为transform-runtime
依赖它。再来个
babel-polyfill
的:行文仓促,多有疏漏,理解上可能有偏差,欢迎各位搞个大新闻。