现状

我们想要用ES6 语法来写 JavaScript。然而由于我们需要兼容老版本的浏览器,那些浏览器不支持 ES6,我们需要解决这个问题。

有一个标准的做法是:写 ES6 代码 → 将所有代码编译成 ES5 的(比如通过 Babel)→ 再将编译后的代码加载到浏览器执行。

这可能已经不再是最有效率的方式了。因为用这种方式,我们强制最新的浏览器运行旧代码,实际上它们完全可以运行最新的代码。它们支持 ES6,我们难道不能直接给它们 ES6 代码吗?

改进方式

有一个 polyfill 项目叫做 Polyfill.io API,它可以通过 polyfill 方式在客户端执行 ES6 代码。

它也实现了一些 HTML 特性的 polyfill,比如 <picture> 元素。

下面是他们网站的描述:

Polyfill.io 读取每个请求的 User-Agent(UA) 头,并生成适合于该浏览器的 polyfill ,基于你的应用所使用的特性发回必要的代码。[...]

Financial Times 在开发和维护这个项目,所以我们能确信这个项目可以持续更新下去,不会死掉。

有一点需要明白:Polyfill.io 没有提供语法糖支持。比如 类、增强的对象字面量,以及箭头函数之类的特性。对那些代码,你仍然需要进行编译。

配置 Polyfill.io

Adding Polyfill.io to your project can be this simple. Add the CDN-hosted script to your page:

要添加 Polyfill.io 到你的项目里非常简单。将托管在 CDN 的脚本添加到你的页面上:

`<script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script>`

运行脚本将返回 UA 和你想要的特性。

  1.  
    UA detected: chrome/56.0.0
  2.  
    Features requested: default

修改请求参数

它提供了一堆选项 来自定义你要返回的特性。

Features

该参数指定需要 polyfill 的浏览器特性。多个特性名之间用逗号分隔。允许使用的特性明在 浏览器和特性 页中列出。

`<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=fetch"></script>`

在 Safari 10 下,脚本返回内容如下:

  1.  
    Features requested: fetch
  2.  
     
  3.  
    - setImmediate, License: CC0 (required by "Promise", "fetch")
  4.  
    - fetch

如果一个特性,比如 fetch 依赖于另一个特性比如 Promise,Polyfill.io 会自动加载依赖。

Flags

  • always - Polyfill 将始终被包含,不管 UA 中指出的浏览器是否已经支持该特性。
  • gated - 通过特性检测来判断 Polyfill,只有在浏览器原生 API 不支持这些特性的情况下才返回并执行 Polyfill。
`<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=fetch&flags=gated"></script>`

Callback

Polyfill 脚本加载完成之后要执行的函数名。这是最简单的在 polyfill 加载完成后触发你自己的代码的方式,这样 polyfill 服务可以更容易通过 async 和 defer 属性被异步加载。

存在的问题

听起来很好,但是仍然不完美。

最新的浏览器不需要加载 ES5 代码了,但是还需要通过服务器请求来检测是否需要 polyfill。

这非常困扰我,因此我正在做一个小项目来改进它。

一个更好的方式

配置 dynamic polyfill

我创建了一个叫做 dynamic-polyfill 的 npm 包。它在发起任何服务端请求前检测特性是否已经被原生支持。

它的配置看起来如下:

  1.  
    import polyfill from 'dynamic-polyfill'
  2.  
     
  3.  
    polyfill({
  4.  
    fills: 'fetch, Promise',
  5.  
    options: 'gated', // default: null
  6.  
    minify: false, // default: true
  7.  
    afterFill() {
  8.  
    main()
  9.  
    }
  10.  
    })
  11.  
     
  12.  
    function main() {
  13.  
    // app code here
  14.  
    }

简单来说,它的执行过程如下:

检测 [window.fetch, window.Promise] 是否存在。

如果存在,运行 afterFill() 回调。

如果它们不存在,创建一个 <script> 标签,并且包含 async 属性,将 Polyfill.io 链接插入,用参数中提供的选项去请求,并在它加载完成后执行 afterFill() 回调。

注意: 现在还没有支持全部选项,只有那些最重要的项被支持。

脚本很小

由于这个模块在压缩后不到 1KB 大小,而且没有任何依赖,对项目使用来说成本超低。

结论

为最新的浏览器写不过时和有效率的 JavaScript,让 Polyfill.io 去处理老版本的的浏览器,如果不必要,别发起额外的 HTTP 请求。

使用 Polyfill 而不再是 bable 来实践js新特性的更多相关文章

  1. QQ音乐:React v16 新特性实践

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由QQ音乐技术团队发表于云+社区专栏 自从去年9月份 React 团队发布了 v16.0 版本开始,到18年3月刚发布的 v16.3 版 ...

  2. MySQL5.6 GTID新特性实践

    MySQL5.6 GTID新特性实践 GTID简介 搭建 实验一:如果slave所需要事务对应的GTID在master上已经被purge了 实验二:忽略purged的部分,强行同步 本文将简单介绍基于 ...

  3. ios7新特性实践

    一 iOS 7 新特性:视图控制器切换API 二 iOS 7系列译文:认识 TextKit 三 iOS 7系列译文:iOS7的多任务处理 四 iOS7 最佳实践:一个天气应用案例(上) 五 iOS7 ...

  4. Spring Boot实践——Spring Boot 2.0 新特性和发展方向

    出自:https://mp.weixin.qq.com/s/EWmuzsgHueHcSB0WH-3AQw 以Java 8 为基准 Spring Boot 2.0 要求Java 版本必须8以上, Jav ...

  5. JDK8新特性:default方法的应用实践

    背景: 最近维护一个老旧工程,遇到集团层面的数据安全改造,需要在DAO层做加解密改造.而这个老旧工程的DAO层是用的JdbcTemplate实现的,尽管template方式实现起来可自由发挥的空间很大 ...

  6. Java8常用新特性实践

    前言: 时下Oracle开速迭代的Java社区以即将推出Java10,但尴尬的是不少小中企业仍使用JDK7甚至JDK6开发. 从上面列出的JDK8特性中我们可以发现Java8的部分特性很明显的是从Sc ...

  7. SAE实践——创建新应用开启MySQL服务

    1. 创建SAE应用 当创建完成SAE账户之后,即可创建SAE应用.点击创建新应用按钮,创建一个新的SAE 应用 阅读提示信息,等待五秒,点继续创建. 填写应用信息完成创建.可选择PHP5.3和空应用 ...

  8. php5.4新特性实践

    本机安装的是wampserver2.2e-php5.4.3-httpd2.2.22-mysql5.5.24-32b.exe集成包 自带了php5.4 1. 数组写法 定义一个数组 过去: $arr = ...

  9. 关于为什么使用React新特性Hook的一些实践与浅见

    前言 关于Hook的定义官方文档是这么说的: Hook 是 React 16.8 的新增特性.它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性. 简单来说,就是在 ...

随机推荐

  1. linux虚拟主机的三种方法

    虚拟主机虚拟主机是将一台(或者一组)服务器的资源(系统资源.网络带宽.存储空间等)按照一定的比例分割成若干相对独立的“小主机”的技术.每一台这样的“小主机”在功能上都可以实现WWW.FTP.Mail等 ...

  2. centos7安装个人网盘owncloud

    现在个人资料越来越重要,网络速度也已经满足日常需要,网盘已经是生活着存取个人数据不可缺少的工具. 下面在linxu centos7下面安装owncloud搭建自己私人网盘: 1.新建一个账号用来安装个 ...

  3. 【转载】使用IntelliJ IDEA 配置Maven(入门)

    1. 下载Maven 官方地址:http://maven.apache.org/download.cgi 解压并新建一个本地仓库文件夹 2.配置本地仓库路径   3.配置maven环境变量      ...

  4. js可以随意拖拽的div的实现

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. 计蒜客 成绩统计 (Hash表)

    链接 : Here! 思路 : 如果用 $STL$ 的 $map$ 或者是使用 $unordered\underline{}map$ 的话是会 $T$ 的, 所以得手写一个 $hash表$. 其实这个 ...

  6. 18清明校内测试T1

    消失的数字(number) Time Limit:1000ms   Memory Limit:128MB 题目描述 rsy拥有n个数,这n个数分别是a1,a2,…,an. 后来出现了一个熊孩子zhw, ...

  7. 【郑轻邀请赛 F】 Tmk吃汤饭

    [题目链接]:https://acm.zzuli.edu.cn/zzuliacm/problem.php?id=2132 [题意] [题解] 很容易想到用队列来模拟; 这个队列维护的是正在煮的4个人煮 ...

  8. 【[Offer收割]编程练习赛13 B】最大子矩阵(别人的思路)

    [题目链接]:http://hihocoder.com/problemset/problem/1502 [题意] [题解] 枚举矩形的最上面的行数和最下面的行数(i,j且i<=j); 然后一个变 ...

  9. Spring学习总结(4)——Spring AOP教程

    一.概念 AOP(Aspect Oriented Programming):面向切面编程. 面向切面编程(也叫面向方面编程),是目前软件开发中的一个热点,也是Spring框架中的一个重要内容.利用AO ...

  10. [HDU3038]How Many Answers Are Wrong(并查集)

    传送门 和某题类似,只不过奇偶换成了和. ——代码 #include <cstdio> #include <iostream> #define N 1000001 int n, ...