polyfill

在es6风靡的时候,babel给了我们一个有力的转换方案,可以在低版本浏览器上写一些新语法而不用考虑兼容问题

polyfill的诞生

语法和API区分

语法是用来产生特殊效果的一些符号

list = [...list]

API分为对象静态、实例方法和函数

这里我们简单区分一下,方便下面展开

babel的局限

为什么会出现polyfill呢,我们都知道,babel是生成AST,然后暴露了AST操作接口插件给我们,AST看起来是一个神秘的东西,但是我们可以大概知道,它是基于当前信息生成了一个代码的另外一个表现形式,但是由于js是动态的,我们是无法得知一个实例调用的方法到底是哪个原型的,这一点就导致了后续产生了很多polyfill的方案,当然一些特殊的语法支持,也需要polyfill

a.includes(x)  // 这里是string还是array呢,我们无法得知

由于上述特性,处理API的编译,尤其困难

实验配置(babel、webpack)

babel

npm i -D  @babel/core @babel/preset-env

npm i @babel/polyfill

.babelrc

{
"presets": [
["@babel/preset-env", {
"useBuiltIns": "entry",
"corejs": 2
}]
]
}

webpack

安装

npm i -D webpack webpack-cli

npm i babel-loader

配置

webpack.config.js

const path = require('path');
module.exports = {
// 开发模式,能看到未压缩的代码
mode: "development",
// 编译入口
entry: './src/index.js',
// 编译出口
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
// 编译规则
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
// 配置babel
loader: 'babel-loader'
}
}
]
}
};

配置脚本

polyfill方案

polyfill的核心就是检测当前是否存在该方法,不存在才使用我们的实现

手动

不推荐

缺点:

非官方实现,很容易出现于规范不一致导致的问题,一些polyfill实现起来也很麻烦,仅用于临时一些修复

if (!Array.prototype.includes) {
Array.prototype.includes = function () {
// 实现
}
}

官方polyfill

babel提供了一个@babel/polyfill包,包括了目前所有的polyfill

以下都基于了新的presets,env的useBuiltIns选项测试

// .babelrc 

{
"presets": [
["@babel/preset-env", {
// "useBuiltIns": "xxx",
}]
]
}

全部导入(entry)

一次性全部导入整个polyfill,是一个彻底的方案

优点:

方便

缺点:

文件很大,所以后续的方案都是针对这个问题做的优化

// .babelrc 

{
"presets": [
["@babel/preset-env", {
"useBuiltIns": "entry",
}]
]
}

我们在webpack主入口导入polyfill

运行npm run start

可以看到完全导入polyfill,打包后的文件增加了400K,polyfill未压缩文件在250K左右,这里有webpack的其他因素影响,但是后续测试也在此条件下进行,可以忽略

entry选项可以支持配置browserlist配置编译目标环境,从而减少编译的代码体积

按需导入(usage)

可以按照我们项目中使用的API,只导入这部分polyfill,同时配合browserlist可以实现代码按需加载同时为运行环境按需加载

优点:

配置方便

体积很少

缺点:

还是没有根据运行环境polyfill,导致所有运行环境被一致polyfill,稍微有点浪费,比如说同时要求IE和谷歌,他们最后的polyfill集合是两者的并集,而不是分开打包的。

使用方法

  1. 去掉我们index.js的import "@babel/polyfill"

  2. useBuiltIns配置改为usage

效果

注意点

browserslist虽然可以按照指定环境检测是否需要polyfill,但是由于其源是can i use上的,其实还是不太精准的,js的polyfill比起css、html的polyfill要求更高,这是一个值得考虑的问题,不过,vue-cli官方采用了这个方案@vue/babel-preset-app,这是基于useBuiltIns: 'usage'和browserslist结合进行polyfill的一个方案

警告

由于babel不会编译node_modules下的包,所以这些依赖如果使用了新特性,此方案不会编译其新语法,一个处理方式就是显式添加polyfill,另外一种方式就是你不知道第三方依赖用了什么,这个时候需要回退到useBuiltIns: 'entry'

UA检测 polyfill

我们可以根据我们使用的新特性传输给服务器,然后服务器检测浏览器的UA,就可以决定真正返回的polyfill了,这个思路实现了真正的环境按需polyfill,不像browserslist一样会取所有兼容环境的并集。

优点:

能够真正按照运行环境进行polyfill

缺点

多一次http请求

UA标志混乱,很可能导致Polyfill缺失

增加服务区成本

polyfill.io

用法

<script src="https://polyfill.io/v3/polyfill.min.js?></script>

非常简单,导入一个cdn即可,但是这个服务是在国外,所以非常慢

阿里fork了它的开源服务,做了如下定制

将polyfill包进行拆分,加入了polyfill.io不认可但是工程需要的polyfill比如说RegeneratorRuntime

编写了标准的UA识别逻辑,大幅大幅降低了响应时间 通常响应时间在 30ms 以内

利用CDN提提供了高可用性的服务

阿里polyfill

https://polyfill.alicdn.com/polyfill.min.js

这个polyfill被正式用到阿里巴巴官方,前几天有看过这个script,最近好像更新为其他的了

polyfill未来

按需特性探测

我们在编码时,工具可以探测源码及node_modules下使用到的特性,返回一个特性列表

在线补丁

就像https://polyfill.io/的方案,我们会检测按需特性探测得到的列表是否在浏览器已经支持,只下载缺失的polyfill

按需特性探测 + 在线补丁才是终极方案

polyfill目前的最佳实践

目前在线补丁这方面还未成熟,我们暂时不使用在这部分,只对按需特性探测进行优化

useBuiltIns: 'usage'和browserslist结合

这里我们对这个方案进行一个优化

不编译第三方包的处理

1.第三方包明确指出了需要的 polyfill

只需要加此polyfill显式加入include配置中去,具体配置可以看文档

2.没有指出需要的polyfill

这个情况暂时没有办法处理,需要回退到useBuiltIns: 'entry'配置

转译API的另外一种方式

优点

1.不会造成全局污染

缺点

1.由于避免全局污染是由助手函数实现的,所以体积会比正常polyfill大

2.暂时不支持[].inclues这样的实例方法

polyfill的问题

polyfill是会污染原型的

if (!Array.prototype.includes) {
Array.prototype.includes = function () {
// 实现
}
}

如果是开发一个组件库,就不能污染原型,因为会导致环境出现一些不可预测的问题

@babel/plugin-transform-runtime

用法

安装

npm install --save-dev @babel/plugin-transform-runtime

npm install --save @babel/runtime

配置

{
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"absoluteRuntime": false,
"corejs": false,
"helpers": true,
"regenerator": true,
"useESModules": false
}
]
]
}

runtime完成的工作

  • 在开启regenerator选项时,自动引入@babel/runtime/regenerator

  • 可以通过corejs定制版本

  • 开启helpers选项,会将内联函数提取为helper函数,统一引入

总结

如果时开发组件库等第三方依赖时,采用babel-runtime机制来实现我们代码的转译,避免对运行环境的污染,在开发应用时,使用正常的polyfill

polyfll方案优化的更多相关文章

  1. 项目四:Java秒杀系统方案优化-高性能高并发实战

    技术栈 前端:Thymeleaf.Bootstrap.JQuery 后端:SpringBoot.JSR303.MyBatis 中间件:RabbitMQ.Redis.Druid 功能模块 分布式会话,商 ...

  2. Devops 开发运维高级篇之Jenkins+Docker+SpringCloud微服务持续集成——部署方案优化

    Devops 开发运维高级篇之Jenkins+Docker+SpringCloud微服务持续集成--部署方案优化 之前我们做的方案部署都是只能选择一个微服务部署并只有一台生产服务器,每个微服务只有一个 ...

  3. C#编程实践–产假方案优化版

    前言 既然作为一个踏踏实实学习技术的人,就要有一颗谦卑.虚心和追求卓越的心,我不能一次就写出很完美的代码,但我相信,踏踏实实一步一步的优化,代码就可以变得趋近完美,至少在某一个特定场景下相对完美,这和 ...

  4. SSD阵列卡方案优化:考虑使用RAID 50替代RAID 10

    最近一直在研究RAID 50,因为牺牲一半的容量的RAID 10代价实在太大了,而且它提供的可用性也并不是百分百的,我们首先来看下RAID 10的可用性分析: 以同等容量的不同RAID方式作为案例分析 ...

  5. 《React-Native系列》44、基于多个TextInput的键盘遮挡处理方案优化

    曾经写过两篇关于在ReactNative上处理键盘遮挡输入表单TextInput的情况.建议读者能够先看看 1.<React-Native系列>33. 键盘遮挡问题处理 2.<Rea ...

  6. Java秒杀系统方案优化 高性能高并发实战(已完成)

    1:商品列表 2:商品详情判断是否可以开始秒杀,未开始不显示秒杀按钮显示倒计时,开始显示秒杀按钮,同时会显示验证码输入框以及验证码图片,当点击秒杀按钮的时候会首先判断验证码是否正确,如果正确会返回一个 ...

  7. Java秒杀系统方案优化 高性能高并发实战(1)

    首先先把 springboot +thymeleaf 搞起来 ,参考 springboot 官方文档 本次学习 使用 springboot + thymeleaf+mybatis+redis+Rabb ...

  8. Authentication 方案优化探索(JWT, Session, Refresh Token, etc.)

    转载自:http://www.jianshu.com/p/5ac8a0e1e5a8

  9. 全面解密QQ红包技术方案:架构、技术实现、移动端优化、创新玩法等

    本文来自腾讯QQ技术团队工程师许灵锋.周海发的技术分享. 一.引言 自 2015 年春节以来,QQ 春节红包经历了企业红包(2015 年).刷一刷红包(2016 年)和 AR 红包(2017 年)几个 ...

随机推荐

  1. CSP-S 2019初赛前后小记

    Preface 做完了初赛前的最后一场模拟赛,虽然这场做的挺好.但由于之前的一场难度很高,再加上自己犯了一些ZZ错误因此对初赛也有了一些不安之情 想起去年自己对于初赛的态度,实在是愧疚虽然去年文化课弃 ...

  2. Mac OSX vim配色方案选择

    首先查看系统自带的vim配色种类: ls /usr/share/vim/vim73/colors 大致输出如下: README.txt default.vim elflord.vim morning. ...

  3. C语言程序设计100例之(12):Eratosthenes筛法求质数

    例12   Eratosthenes筛法求质数 问题描述 Eratosthenes筛法的基本思想是:把某范围内的自然数从小到大依次排列好.宣布1不是质数,把它去掉:然后从余下的数中取出最小的数,宣布它 ...

  4. centos6和centos7的防火墙基本命令

    一.centos6: 1.firewall的基本启动/停止/重启命令 $查看防火墙状态: service iptables status (/etc/init.d/iptables status) $ ...

  5. 1+x证书Web前端开发HTML+CSS专项练习测试题(八)

    1+x证书Web前端开发HTML+CSS专项练习测试题(八) 官方QQ群 1+x 证书 Web 前端开发 HTML+CSS 专项练习测试题(八) http://blog.zh66.club/index ...

  6. SecureCRT连接本地虚拟机Linux系统很慢

    SSH配置问题 cd /etc/ssh/ 备份一下配置文件 cp sshd_config sshd_config.2019-07-17.bak 修改配置 vim sshd_config 重启sshd服 ...

  7. java高并发系列 - 第10天:线程安全和synchronized关键字

    这是并发系列第10篇文章. 什么是线程安全? 当多个线程去访问同一个类(对象或方法)的时候,该类都能表现出正常的行为(与自己预想的结果一致),那我们就可以所这个类是线程安全的. 看一段代码: pack ...

  8. java高并发系列 - 第3天:有关并行的两个重要定律

    有关为什么要使用并行程序的问题前面已经进行了简单的探讨.总的来说,最重要的应该是处于两个目的. 第一,为了获得更好的性能: 第二,由于业务模型的需要,确实需要多个执行实体. 在这里,我将更加关注第一种 ...

  9. Python爬取知乎上搞笑视频,一顿爆笑送给大家

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:Huangwei AI 来源:Python与机器学习之路 PS:如有需 ...

  10. python xlwt模块简介

    一.基础类介绍 1.工作簿类Workbook简介: import xlwt class Workbook(object0): ''' 工作簿类,使用xlwt创建excel文件时,首先要实例化此类的对象 ...