现状

我们想要用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. (转)Hibernate的一级缓存

    http://blog.csdn.net/yerenyuan_pku/article/details/70148567 Hibernate的一级缓存 Hibernate的一级缓存就是指Session缓 ...

  2. php 在不知道字符串有多长的情况下,如何去除前三个字符?

    $string='字符串';$subject=substr_replace(string,'',0,3);

  3. 最快的 Python Web 框架入门

    速度比较 框架 实现基础 每秒请求数 平均时间 Sanic Python 3.5 + uvloop 30,601 3.23ms Wheezy gunicorn + meinheld 20,244 4. ...

  4. How To: set udev rule for setting the disk permission on ASM disks when using multipath on Linux 6.x

    在RHEL6.4上安装11gR2的RAC时,使用了MULTIPATH来聚合绑定多路径的磁盘,并且修改磁盘的权限,赋予grid:asmadmin用户和组. 此时,在安装时可以发现磁盘,日志如下 INFO ...

  5. [luogu2591 ZJOI2009] 函数

    传送门 Solution 画图找规律.. Code //By Menteur_Hxy #include <cstdio> #define min(a,b) ((a)>(b)?(b): ...

  6. Linux之iptables(一、防火墙的概念)

    防火墙的概念 一.安全技术 入侵检测与管理系统(Intrusion Detection Systems):特点是不阻断任何网络访问,量化.定位来自内外网络的威胁情况,主要以提供报告和事后监督为主,提供 ...

  7. python下操作mysql 之 pymsql

    python下操作mysql  之  pymsql pymsql是Python中操作MySQL的模块, 下载安装: pip3 install pymysql 使用操作 1, 执行SQL #!/usr/ ...

  8. Jquery书写ajax

    根据API学习本章 Jquery书写ajax 使用ajax发送表单到servlet,发送时显示等待图片,servlet处理完返回信息,在页面显示返回信息,并且隐藏等待图片 <%@ page la ...

  9. RDS for MySQL 通过 mysqlbinlog 查看 binlog 乱码

    问题描述: 使用 mysqlbinlog -vv mysql-bin.000110 查看 RDS mysql 二进制文件发现类似如下结果: BINLOG ' MgI+UA8BAAAAZwAAAGsAA ...

  10. CF #328div2 D

    这题不难,当时想出来了,可是却写不出来~~ 现在慢慢写回来,也写得好挫~ 可以知道,被攻击的城市必定可以组成一棵树,然后,传送到的点必定也是城市之一.如果出发后回到原点,则需要2E,E是树的边数,则2 ...