Javascript 使用 ES6 和 ES7 功能的库是否需要 babel-polyfill?
Should Javascript library which uses ES6 and ES7 features require babel-polyfill?
我正在开发一个大量使用 ES6 和 ES7 功能的库。用 Babel 编译它会产生代码,它(自然地)使用 Symbol 或 Promise 等原语。我是否应该 require('babel-polyfill')
确保这些原语确实存在?
一开始,答案似乎是 'yes' - 特别是如果我不知道有人可能会在什么运行时执行我的库。另一方面,如果每个图书馆都这样做,我们最终会一遍又一遍地要求 babel-polyfill
(我不确定这是否是个好主意)。
我对此做了一些研究:
从库内部要求 babel-polyfill
看起来像 anti-pattern;这有两个原因:
1) babel-polyfill
不喜欢被要求多次,如果你尝试这样做,它会抛出错误(见下面的注释)
2) 这样做会导致库的大小显着增加,因为您必须多次捆绑 polyfill。
仅当 npm
无法删除多个 babel-polyfill
依赖项时,1) 和 2) 才相关。如果您使用旧版本的 npm
或由于依赖限制可能无法进行重复数据删除,就会发生这种情况。由于最新的不容易控制,所以我认为1)和2)都很严重。
现在,你(可能)应该怎么做:
如果您需要库中的特定功能(即 Promise),您可以 require
具体地使用它(即不是整个 polyfill,只是功能)。这种方法缓解了 1) 并部分缓解了 2).
可能最好的方法就是警告您的用户,您的库需要一些 ES6 功能,因此他们应该需要 polyfill。
第一种方法的很好的例子是
https://www.npmjs.com/package/promisify-node
这需要它自己的 A+ 兼容 Promise 版本。第二种方法的好例子是
https://github.com/ubolonton/js-csp
它使用了生成器,但没有做任何事情来确保它们确实存在(一般来说,仅仅用 Babel 编译代码是不够的,你需要一个 polyfill 来使它们工作)。
--------编辑--------
我发现,babel-plugin-transform-runtime
可以准确地用于解决这个问题:它允许您使用 ES6 / ES7 功能,而无需通过 polyfill 污染全局命名空间。这个故事的可悲部分是,这个插件有很多错误,可能是因为从根本上很难完成这项工作。例如:
Object.keys({})
转换为类似于:
var _keys=require("babel-runtime/core-js/object/keys")
_keys(obj)
但是
var aaa = Object
aaa.keys(obj)
根本不会被转换,因此会失败(如果 Object.keys 既没有被浏览器定义,也没有被 polyfill 定义)。我的建议是 - 不要将插件用于此目的。
我正在开发一个大量使用 ES6 和 ES7 功能的库。用 Babel 编译它会产生代码,它(自然地)使用 Symbol 或 Promise 等原语。我是否应该 require('babel-polyfill')
确保这些原语确实存在?
一开始,答案似乎是 'yes' - 特别是如果我不知道有人可能会在什么运行时执行我的库。另一方面,如果每个图书馆都这样做,我们最终会一遍又一遍地要求 babel-polyfill
(我不确定这是否是个好主意)。
我对此做了一些研究:
从库内部要求 babel-polyfill
看起来像 anti-pattern;这有两个原因:
1) babel-polyfill
不喜欢被要求多次,如果你尝试这样做,它会抛出错误(见下面的注释)
2) 这样做会导致库的大小显着增加,因为您必须多次捆绑 polyfill。
仅当 npm
无法删除多个 babel-polyfill
依赖项时,1) 和 2) 才相关。如果您使用旧版本的 npm
或由于依赖限制可能无法进行重复数据删除,就会发生这种情况。由于最新的不容易控制,所以我认为1)和2)都很严重。
现在,你(可能)应该怎么做:
如果您需要库中的特定功能(即 Promise),您可以 require
具体地使用它(即不是整个 polyfill,只是功能)。这种方法缓解了 1) 并部分缓解了 2).
可能最好的方法就是警告您的用户,您的库需要一些 ES6 功能,因此他们应该需要 polyfill。
第一种方法的很好的例子是
https://www.npmjs.com/package/promisify-node
这需要它自己的 A+ 兼容 Promise 版本。第二种方法的好例子是
https://github.com/ubolonton/js-csp
它使用了生成器,但没有做任何事情来确保它们确实存在(一般来说,仅仅用 Babel 编译代码是不够的,你需要一个 polyfill 来使它们工作)。
--------编辑--------
我发现,babel-plugin-transform-runtime
可以准确地用于解决这个问题:它允许您使用 ES6 / ES7 功能,而无需通过 polyfill 污染全局命名空间。这个故事的可悲部分是,这个插件有很多错误,可能是因为从根本上很难完成这项工作。例如:
Object.keys({})
转换为类似于:
var _keys=require("babel-runtime/core-js/object/keys")
_keys(obj)
但是
var aaa = Object
aaa.keys(obj)
根本不会被转换,因此会失败(如果 Object.keys 既没有被浏览器定义,也没有被 polyfill 定义)。我的建议是 - 不要将插件用于此目的。