大家好,很高興又見面了,我是"進階前端進階",由我帶着大家一起關注前端前沿、深入前端底層技術,大家一起進步,也歡迎大家關注、點贊、收藏、轉發!
進階前端進階
今天給大家帶來的主題是周均下載下傳百萬+的TOP 12前端 Ponyfill,不了解polyfill、ponyfill的可以預先閱讀我的另外一篇文章:
《前端 Polyfill、Ponyfill、Prollyfill 傻傻分不清楚?》
話不多說,直接開始!
什麼是Ponyfill
和Polyfill相比,ponyfill 的做法更聰明一些:它不會污染全局範圍,而是将功能導出為子產品。 例如,一個 Number.MAX_SAFE_INTEGER ponyfill 的例子可以是:
module.exports = 9007199254740991
// 使用子產品導出
重要的是不要在 ponyfill 實作中使用本地方法,因為環境差異,這些方法可能表現不同。如果你想使用本地方法,你可以将它包裝在子產品 escope 之外:
const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || require('number-max-safe-integer')
// 做下代碼相容
了解了Polyfill以及實作Polyfill的注意事項後,接下來一起看看有哪些熱門的前端Polyfill。
es6-symbol
ECMAScript 6 Symbol polyfill。如果開發者想在 Symbol 存在時使用原生版本,如果它不存在則回退到 ponyfill,可以使用 es6-symbol 如下:
var Symbol = require('es6-symbol');
如果想在全局環境中使用 Symbol,可以通過下面的方式:
require('es6-symbol/implement');
如果想一直使用 polyfill,即使原生 Symbol 存在,可以通過下面方式:
var Symbol = require('es6-symbol/polyfill');
下面是使用 es6-symbol 的完整示例。
var Symbol = require('es6-symbol');
var symbol = Symbol('My custom symbol');
var x = {};
x[symbol] = 'foo';
console.log(x[symbol]);
('foo');
// Detect iterable:
var iterator, result;
if (possiblyIterable[Symbol.iterator]) {
iterator = possiblyIterable[Symbol.iterator]();
result = iterator.next();
while (!result.done) {
console.log(result.value);
result = iterator.next();
}
}
目前 es6-symbol 在 NPM 的周平均下載下傳量達到了 11,150K,超過了 1115W。
object-assign
ES2015 Object.assign() 的 ponyfill。Node.js 4 及更高版本,以及主流浏覽器(Chrome、Edge、Firefox、Opera、Safari)都支援 Object.assign() ,但是 object-assign 這個包可用于相容更糟糕的浏覽器、Node 環境。使用方法如下:
const objectAssign = require('object-assign');
objectAssign({ foo: 0 }, { bar: 1 });
//=> {foo: 0, bar: 1}
// multiple sources
objectAssign({ foo: 0 }, { bar: 1 }, { baz: 2 });
//=> {foo: 0, bar: 1, baz: 2}
// overwrites equal keys
objectAssign({ foo: 0 }, { foo: 1 }, { foo: 2 });
//=> {foo: 2}
// ignores null and undefined sources
objectAssign({ foo: 0 }, null, { bar: 1 }, undefined);
//=> {foo: 0, bar: 1}
目前 object-assign 在 NPM 的周平均下載下傳量達到了 35,883K,超過了 3500W。
path-parse
用于 Node.js 環境的 path.parse(pathString) 的 ponyfill,基礎用法如下:
var pathParse = require('path-parse');
pathParse('/home/user/dir/file.txt');
//=> {
// root : "/",
// dir : "/home/user/dir",
// base : "file.txt",
// ext : ".txt",
// name : "file"
// }
目前 path-parse 在 NPM 的周平均下載下傳量達到了 35,664K,超過了 3566W。
es6-weak-map
受到 Mark Miller 和 Kris Kowal 的 WeakMap 實作的啟發。 差別是:
- 假設有相容的 ES5 環境(沒有奇怪的 ES3 解決方法或 hack)
- 良好的子產品化 CJS 風格
- 基于獨立的解決方案
如果想確定您的環境實作了 WeakMap,請執行以下操作:
require('es6-weak-map/implement');
如果想在本地版本存在時使用它,如果不存在則回退到 polyfill,但又不想在全局範圍内實作 WeakMap,請執行以下操作:
var WeakMap = require('es6-weak-map');
如果即使原生 WeakMap 存在,你也确實想使用 polyfill,請執行以下操作:
var WeakMap = require('es6-weak-map/polyfill');
下面是使用 es6-weak-map 的完整示例:
var WeakMap = require('es6-weak-map');
var map = new WeakMap();
var obj = {};
map.set(obj, 'foo'); // map
map.get(obj); // 'foo'
map.has(obj); // true
map.delete(obj); // true
map.get(obj); // undefined
map.has(obj); // false
map.set(obj, 'bar'); // map
map.has(obj); // false
目前 es6-weak-map 在 NPM 的周平均下載下傳量達到了 5,622K,超過了 560W。
array-find
ES 2015 Array.find 的 ponyfill,用于查找數組元素。為每個元素執行回調,傳回其回調傳回真值的第一個元素。用法如下:
var find = require('array-find');
var numbers = [1, 2, 3, 4];
find(numbers, function (element, index, array) {
return element === 2;
});
// => 2
var robots = [{ name: 'Flexo' }, { name: 'Bender' }, { name: 'Buster' }];
find(robots, function (robot, index, array) {
return robot.name === 'Bender';
});
// => {name: 'Bender'}
find(robots, function (robot, index, array) {
return robot.name === 'Fry';
});
// => undefined
目前 array-find 在 NPM 的周平均下載下傳量達到了 1,433K,超過了 140W。
array-from
ES 2015 Array.from() 的 ponyfill,與 ES 2015 規範保持一緻。
var arrayFrom = require('array-from');
// You’ll get the native `Array.from` if it’s available.
function () {console.log(
arrayFrom(arguments).map(require('1-liners/increment'))
);}(1, 2, 3);
//» [2, 3, 4]
也可以将其用作經典的 polyfill,雖然不推薦,但有時确實實用:
if (!Array.from) Array.from = require('array-from');
// This will affect all loaded modules.
function () {console.log(
Array.from(arguments).map(require('1-liners/increment'))
);}(1, 2, 3);
//» [2, 3, 4]
目前 array-from 在 NPM 的周平均下載下傳量達到了 1,984K,超過了 190W。
es6-map
ECMAScript6 中指定 Map 集合的 ponyfill,使用 es6-map 作為 ponyfill 是最安全的,它是一個不接觸全局對象的 polyfill:
var Map = require('es6-map');
如果想確定全局環境存在 Map,請執行以下操作:
require('es6-map/implement');
如果即使原生 Map 存在,你也确實想使用 polyfill,請執行以下操作:
var Map = require('es6-map/polyfill');
目前 es6-map 在 NPM 的周平均下載下傳量達到了 1,596K,超過了 159W。
array-find-index
ES2015 Array#findIndex()的 ponyfill,由前端大神 Sindre Sorhus 編寫,用法如下:
const arrayFindIndex = require('array-find-index');
arrayFindIndex(['rainbow', 'unicorn', 'pony'], (x) => x === 'unicorn');
//=> 1
目前 array-find-index 在 NPM 的周平均下載下傳量達到了 7,655K,超過了 760W。
@whatwg-node/fetch
Fetch 标準 的 ponyfill 包。 如果 JavaScript 環境本身沒有實作這個标準,這個包會自動填充缺失的部分,并将它們導出為一個子產品, 否則它會在不觸及環境内部的情況下導出原生的 fetch。 它還導出 Fetch 标準所需的一些額外的标準 API。
下面示例使用 Fetch API 處理檔案上傳:
import { Request } from '@whatwg-node/fetch';
// See how you can handle file uploads with Fetch API
http.createServer(async (req, res) => {
const request = new Request(req);
const formData = await request.formData();
const file = formData.get('file');
// ...
});
下面示例限制表單資料大小:
import { createFetch } from '@whatwg-node/fetch';
const fetchAPI = createFetch({
formDataLimits: {
// Maximum allowed file size (in bytes)
fileSize: 1000000,
// Maximum allowed number of files
files: 10,
// Maximum allowed size of content (operations, variables etc...)
fieldSize: 1000000,
// Maximum allowed header size for form data
headerSize: 1000000,
},
});
// See how you can handle file uploads with Fetch API
http.createServer(async (req, res) => {
const request = new Request(req);
const formData = await request.formData();
const file = formData.get('file');
// ...
});
目前 @whatwg-node/fetch 在 NPM 的周平均下載下傳量達到了 3,656K,超過了 360W。
css-vars-ponyfill
css-vars-ponyfill 為遺留和現代浏覽器中的 CSS 自定義屬性(又名“CSS 變量”)提供用戶端支援。
/* style.css */
:root {
--a: var(--b); /* Chained */
--b: var(--c);
--c: 10px;
}
div {
color: var(--color); /* from <style> */
margin: var(--unknown, 20px); /* Fallback */
padding: calc(2 * var(--a)); /* Nested */
}
使用首選選項調用 ponyfill:
/* main.js */
cssVars({
// Options...
});
輸出結果如下:
div {
color: black;
margin: 20px;
padding: calc(2 * 10px);
}
目前 css-vars-ponyfill 在 NPM 的周平均下載下傳量達到了 143K,超過了 14W。
path-dirname
Node.js 的 path.dirname() ponyfill,這是為了在 Node.js v0.10 上導出 path.posix.dirname() 所必需的。
const pathDirname = require('path-dirname');
pathDirname('/home/foo');
//=> '/home'
pathDirname('C:\\Users\\foo');
//=> 'C:\\Users'
pathDirname('foo');
//=> '.'
pathDirname('foo/bar');
//=> 'foo'
//Using posix version for consistent output when dealing with glob escape chars
pathDirname.win32('C:\\Users\\foo/\\*bar');
//=> 'C:\\Users\\foo/'
pathDirname.posix('C:\\Users\\foo/\\*bar');
//=> 'C:\\Users\\foo'
目前 path-dirname 在 NPM 的周平均下載下傳量達到了 12,776K,超過了 1270W。
fromentries
Object.fromEntries() 的 ponyfill。現有的 polyfill 包(如 object.fromentries)引入了一堆依賴項,并增加了超過 8 KB 的浏覽器包大小,進而可以在 IE6 等 ES3 環境中工作,但也有點矯枉過正,因為幾乎沒有人支援 IE6 了。
fromentries 使用現代語言功能在幾行代碼中實作此功能的 polyfill。
const fromEntries = require('fromentries');
const map = new Map([
['a', 1],
['b', 2],
['c', 3],
]);
const obj = fromEntries(map);
constole.log(obj); // { a: 1, b: 2, c: 3 }
const searchParams = new URLSearchParams('foo=bar&baz=qux');
const obj2 = fromEntries(searchParams);
console.log(obj2); // { foo: 'bar', 'baz': 'qux' }
目前 fromentries 在 NPM 的周平均下載下傳量達到了 3,548K,超過了 350W。
es6-object-assign
ECMAScript 2015 (ES2015/ES6) Object.assign() 用于 ECMAScript 5 環境的 polyfill 和 ponyfill。
該包還可以作為 UMD 子產品(與 AMD、CommonJS 相容并公開全局變量 ObjectAssign)在 dist/object-assign.js 和 dist/object-assign.min.js(壓縮後 833 位元組)中使用。
具有自動 polyfilling 的版本是 dist/object-assign-auto.js 和 dist/object-assign-auto.min.js。
// Polyfill, modifying the global Object
require('es6-object-assign').polyfill();
var obj = Object.assign({}, { foo: 'bar' });
// Same version with automatic polyfilling
require('es6-object-assign/auto');
var obj = Object.assign({}, { foo: 'bar' });
// Or ponyfill, using a reference to the function without modifying globals
var assign = require('es6-object-assign').assign;
var obj = assign({}, { foo: 'bar' });
目前 es6-object-assign 在 NPM 的周平均下載下傳量達到了 2,394K,超過了 230W。
fetch-ponyfill
WHATWG fetch 的 ponyfill。該子產品将 github/fetch polyfill 包裝在 CommonJS 子產品中以實作浏覽器化,并避免向 window 附加任何方法。
在 Node 中使用時,能力由 node-fetch 提供。
import fetchPonyfill from 'fetch-ponyfill';
const { fetch, Request, Response, Headers } = fetchPonyfill(options);
目前 fetch-ponyfill 在 NPM 的周平均下載下傳量達到了 290K,超過了 29W。
本文總結
本文主要和大家介紹周均下載下傳百萬+的TOP 12前端 Ponyfill 。因為篇幅有限,文章并沒有就每一個Ponyfill過多展開,如果有興趣,可以直接在我首頁繼續閱讀,但是文末的參考資料提供了大量優秀文檔以供學習。最後,歡迎大家點贊、評論、轉發、收藏!
參考資料
https://www.npmjs.com/package/es6-symbol
https://www.npmjs.com/package/object-assign
https://www.npmjs.com/package/path-parse
https://www.npmjs.com/package/es6-weak-map
https://www.npmjs.com/package/array-find
https://www.npmjs.com/package/es6-map
https://www.npmjs.com/package/array-find-index
https://www.npmjs.com/package/@whatwg-node/fetch
https://www.npmjs.com/package/css-vars-ponyfill
https://www.npmjs.com/package/path-dirname
https://www.npmjs.com/package/es6-object-assign
https://www.npmjs.com/package/fetch-ponyfill