前端发展到今天,很多新特性并不能直接在浏览器中使用,尤其是在移动端,所以我们经常会需要引入polyfill。那么问题来了,我们应该如何优雅地引入polyfill呢?
这里我提到的优雅包括以下几方面:
- 对开发者友好
- 不与标准冲突
- 不重复引入多余的代码
下面从应用(application)和库(library)的角度分别来探讨一下引入polyfill的方案。
应用
应用中引入一个polyfill其实不需要考虑太多,因为这里完全是我们的地盘,不用担心对其他代码造成副作用。那么最直接的方法就是引入标准中存在而实际中不存在的全局变量,以Promise
为例:
// 直接从core-js引入全局的polyfill
import 'core-js/fn/promise';
当我们使用了babel的情况下,如果开启了babel-plugin-transform-runtime
,我们会发现,代码中用到Promise
的地方都被babel进行了转换,自动转换成了babel-runtime/core-js/promise
,实际上就是一个不污染全局的core-js
的polyfill,相当于core-js/library/fn/promise
。通过分析代码,我们会发现,core-js/library/fn/promise
和core-js/fn/promise
引入了两套大同小异的代码,一套不会污染全局,一套会直接挂载到window
上。这种引入重复代码的行为显然是不优雅的。
考虑到良好的开发体验,直接使用Promise
让babel转换更加自然,不用每次都去引入,显然我们更愿意接受babel-plugin-transform-runtime
的polyfill。
但是有些第三方库可能也会依赖Promise
,他们却不会被babel处理,这时就需要从window
上获取,所以还是需要挂载到window上,而且这样也是符合ES6标准的。
一个简短的写法如下:
// 如果开启了babel-plugin-transform-runtime,则
window.Promise = window.Promise || Promise;
库
第三方库通常不应该去直接依赖其他公共库,这样有可能会导致重复的依赖或者不同版本间的冲突。比如Promise
可以有不同的实现,我们应该交由应用代码去选择,比如移动端倾向于选择更小的实现。
所以在库里面,我们只要按照ES6规范去使用Promise
就好了,在编译的时候也不需要进行特殊处理。然后在文档里面告诉用户:
我们是依赖
Promise
的,请自行配置polyfill喔。
网友评论