Never worry about polyfills again.
This is a web service that returns a minified and encoded bundle of only the polyfills your users need.
It's like polyfill.io, but it has additional polyfills such as Web Components, Pointer Events, and much more.
It is also potentially faster since all unique polyfill combinations are cached in memory and returned immediately as requested.
And, it supports different kinds of encodings for the smallest possible network bandwidth overhead, including Brotli and Gzip.
The web service is hosted and live at https://polyfill.app/api
. It is free to use, and there are no quota limits. See the Hosting section for details on how to host it yourself, if you want to.
- Sends only the polyfills your users actually need
- Wide range of polyfills for modern technologies such as Web Components, Pointer Events, Intl (including
RelativeTimeFormat
andListFormat
), and much more. - Automatic deduplication and insertion of missing dependencies of requested polyfills
- Supports multiple environments, including Browsers, Workers, and even Node.
- Brotli and Gzip compression
- Intelligent disk- and memory caching for maximum speed and availability
- Completely free
Polyfiller is kindly supported by and relies heavily on BrowserStack for cross-browser testing to ensure maximum cross-browser compatibility.
Polyfiller is kindly supported by JetBrains for software development tools:
Become a sponsor/backer and get your logo listed here.
Bubbles Twitter: @usebubbles |
Xerox | Trent Raymond | scrubtheweb | Joel |
- Description
- Supporters
- Backers
- Table of Contents
- Install
- Usage
- Examples
- Web Service API Reference
- Contributing
- Maintainers
- FAQ
- Logo
- License
$ npm install @wessberg/polyfiller
$ yarn add @wessberg/polyfiller
$ pnpm add @wessberg/polyfiller
Polyfiller
is already hosted at https://polyfill.app/api
as a free web service, but you can install it, for example if
you want to host it yourself. See the Hosting section for more details on that.
Polyfiller
can be used both in a Browser, Worker, and Node environment. By default, the assumed environment is Browser.
Place a <script>
tag inside your index.html
file with a src
pointing at https://polyfill.app/api/polyfill
.
In the following example, polyfills for ES2015
and Shadow DOM
are requested:
<!-- An example of requesting polyfills for an ES2015 environment as well as Web Component support
-->
<script crossorigin src="https://polyfill.app/api/polyfill?features=es,web-components"></script>
A targeted bundle will be returned that only contains the specific polyfills the browser needs!
When a browser (or robot) visits your site, Polyfiller
evaluates the user agent against Caniuse and decides what is supported and what isn't.
It is up to you to decide which polyfills you need, but the web service will automatically make sure to include every dependency of those polyfills, but only if the browser doesn't already support them.
See this or this section for details on how to use Polyfiller
from Web Workers/ServiceWorkers and Node.
You can provide options to Polyfiller via query parameters such as minify
and sourcemap
to adjust the received payload to your liking.
In this example:
es
polyfills those EcmaScript features that the browser doesn't support.intersection-observer
is polyfilled, even if the browser supports it, because it has theforce
option.intl
is polyfilled, with the inclusion ofIntl.ListFormat
andIntl.RelativeTimeFormat
, if the browser doesn't support it, and theen
locale data is included.- Sourcemaps are generated, and the bundle is minified
<script crossorigin src="https://polyfill.app/api/polyfill?minify&sourcemap&features=es,intersection-observer|force,intl|locale=en"></script>
This example shows how you can add support for Web Components:
template
polyfills theHTMLTemplateElement
if the browser doesn't support it.shadow-dom
polyfills theShadow DOM
v1 specification if the browser doesn't support it.custom-elements
polyfills theCustom Elements
v1 specification if the browser doesn't support it.
<script crossorigin src="https://polyfill.app/api/polyfill?features=template,shadow-dom,custom-elements"></script>
For your convenience, the web-components
alias requests those three features.
<script crossorigin src="https://polyfill.app/api/polyfill?features=web-components"></script>
For your convenience, a few libraries are included that isn't strictly polyfills but are closely related to compatibility: In this example:
systemjs
Adds theSystemJS
ES module loader. Useful if you target a browser that doesn't support ES-modules and want to use something like dynamic imports and code-splitting.regenerator-runtime
is added, which is what babel transpiles async functions and generator functions into if you don't target browsers that supports it.
<script crossorigin src="https://polyfill.app/api/polyfill?features=systemjs,regenerator-runtime"></script>
Retrieves a bundle of polyfills.
Polyfiller
will use the incoming Accept-Encoding
headers of the request to decide if the response should be Brotli
encoded, Gzip
encoded or not encoded at all.
Parameter | Description |
---|---|
features |
A comma-separated string of all the feature s you want to include in your bundle (if required by the browser). Each feature may receive zero or more option s. Some option s are supported for all feature s while others only support specific feature s. |
context |
Can be either window , worker , or node . Use this to instruct Polyfiller to optimize polyfills for the given environment, as well as to exclude polyfills that doesn't support the given context. |
sourcemap |
If given, or if it has a value of true , Polyfiller will be instructed to generate SourceMaps. Use this in development for better stack traces. |
minify |
If given, Polyfiller will send back a minified Polyfill bundle. |
A feature
has a name and may receive zero or more option
s.
For example, intl
is a feature name, and so is custom-elements
.
See the Feature name section for the full list of possible feature
names.
An option
is some data associated with a feature
.
It is associated with a feature using the |
(pipe) operator.
For example, here's how to associate the force
option with a feature
:
animation|force
.
Some option
s apply to all feature
s while others only apply to specific feature
s. For example:
intl|locale=en
By default, feature
s that are already supported by the browser sending the request to the web service won't be polyfilled. That would be a waste of network bandwidth and parsing cost for your users.
However, sometimes you may want to force a polyfill, even for browsers that support a feature
.
In order to do so, associate the force
option with a feature
. For example:
animation|force
This will force-apply a polyfill for Web Animations
.
This option only works with intl
, intl.core
, intl.list-format
, or intl.relative-time-format
.
The Intl
family of polyfills rely on locale data for them to work. There are over 600 different locale files shipped. Sending all of them back over the network would take way too much bandwidth.
Instead, if you just ask for the intl
, intl.core
, intl.list-format
, or intl.relative-time-format
features, they will be returned without any locale data.
To add one or more locales, use the locale
option. For example:
intl|locale=en
This will return a bundle of Intl
-related polyfills along with locale data for the en
(English) language code.
You can ask for as many you want by separating the locales with the ~
operator. For example:
intl|locale=en~da~fr
This will return a bundle of Intl
-related polyfills along with locale data for en
(English), da
(Danish), and fr
(French).
SystemJS comes in two base versions, a minimal version called s, and a more feature-complete version called system.
By default, the system variant will be used. You can decide which one to use with the variant
option.
For example: systemjs|variant=s
selects the s variant, while systemjs|variant=system
selects the system variant.
Zone.js, which is supported by Polyfiller, can be configured with some extra options to enhance its operation or support interoperability with more APIs:
Option | Description |
---|---|
error |
Generates more readable Stack traces when using Zone |
shadydom |
Makes Zone compatible with the ShadyDOM polyfill. |
mediaquery |
Patches the Media Query API |
fetch |
Patches the Fetch API. |
resizeobserver |
Patches the ResizeObserver API. |
Option | Description |
---|---|
experimental |
You can pass the experimental option to shadow-dom (or any of its aliases such as web-components ) to base it on some experimental features that may reduce bugs in older browsers such as IE and Edge <= 15. |
lit |
If you're going to be using Lit, you can also pass the lit option to shadow-dom (or any of its aliases such as web-components ) to include its polyfill support layer. |
You can also request polyfills from a Worker. It is highly recommended that you pass in the context
query parameter with a value of worker
to instruct Polyfiller
to optimize polyfills for a Worker environment, as well as to
not include any polyfills that won't work in a Worker environment.
// Provide a context query parameter with a value of 'worker' to avoid polyfills that doesn't support that environment
importScripts("https://polyfill.app/api/polyfill?features=es,intl,web-animations&context=worker");
You can also request polyfills from Node, if that's a thing you want to do. It is highly recommended that you pass in the context
query parameter with a value of node
to instruct Polyfiller
to optimize polyfills for a Node environment, as well as to
not include any polyfills that won't work in a Node environment.
(async () => {
// Remember to provide a user agent header if you want anything meaningful back
const response = await fetch("https://polyfill.app/api/polyfill?features=intl&context=node");
const text = await response.text();
// Apply the polyfills
new Function(text)();
})();
Do you want to contribute? Awesome! Please follow these recommendations.
Frederik Wessberg Twitter: @FredWessberg Github: @wessberg Lead Developer |
These two services are very much alike. In fact, Polyfiller
depends on the library behind polyfill.io for some of the polyfills!
Polyfiller
exists for two reasons:
- A wider range of available polyfills such as Web Components, PointerEvents and Proxies
- Deep integration with
Caniuse
. If you use something likebabel-preset-env
with abrowserslist
and you generate this automatically based on the features you want to support with a tool such as browserslist-generator, both syntax detection for transpiling, and feature detection for polyfilling will be seamlessly based on yourbrowserslist
.
Polyfiller
is already hosted at https://polyfill.app/api
as a free web service, but feel free to host it yourself.
The server is built with support for both HTTP2 and HTTP. The environment variable HTTP2=[true|false]
decides whether a HTTP2 server will be hosted or not.
If you use a load balancer and something like nginx
in a reverse proxy setup, please know that nginx
doesn't support HTTP2 via its proxy module, so you have to use HTTP1.1 there. Thankfully, it is as easy as setting HTTP2=false
before launching the server and setting HTTPS=false
.
This guide has been tested in the deployment process of China mirror: https://polyfiller.kaiyuanshe.cn
In the development environment, use installation script
curl -fsSL https://get.docker.com | sudo sh
add the current user to the docker
user group
sudo gpasswd -a ${USER} docker
You need to press CTRL + D to log out of the session, then use SSH to log back into the system.
Docker-install-script says It is not recommended to depend on this script for deployment to production systems
.
So depend on your choice.
Find more information in the Docker install document.
Rclone use FUSE
mount the Rclone's cloud storage systems, you need to install it.
In Debian(Ubuntu)
sudo apt install fuse3 -y
In CentOS
sudo yum install epel-release
sudo yum update
sudo yum install fuse3
In Fedora
sudo dnf install fuse3
In Arch
sudo pacman -Syu fuse3
Run shown commands in the Project Root folder:
docker build -t polyfiller/api-service .
docker run --name polyfiller -e NODE_ENV=production -p 3000:3000 polyfiller/api-service
- Write Rclone config into
config/rclone/rclone.conf
file of your Project:
[azure]
type = azureblob
account = xxxx
key = xxxx
endpoint = https://xxx
How to configure quickly? Use rclone config
command? It needs to know a lot of things. Open Document, choose an instructions, like Dropbox.
Look for
[remote]
app_key =
app_secret =
token = XXXXXXXXXXXXXXXXXXXXXXXXXXXXX_XXXX_XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
It is the configuration for Dropbox.
[dropbox]
type = dropbox
app_key = xxxxxxxxx
app_secret = xxxxxxxxx
token = XXXXXXXXXXXXXXXXXXXXXXXXXXXXX_XXXX_XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
If you use Dropbox, in docker-compose.yml
:
command: "mount azure:/ /polyfill-cache --allow-other --allow-non-empty --vfs-cache-mode writes"
It should be changed to:
command: "mount dropbox:/ /polyfill-cache --allow-other --allow-non-empty --vfs-cache-mode writes"
- Run shown commands in the Project Root folder:
docker compose up -d
- Set GitHub Repository secrets:
name | value |
---|---|
RCLONE_FILE |
rclone configuration file |
ENV_FILE |
.env file shown above |
HOST |
IP or Domain Name of Cloud Server |
USER |
Account Name of Cloud Server |
SSH_KEY |
SSH Private Key of Cloud Server |
- Push a Git tag:
git tag v0.2.3-oss # the version number is the value of "version" field in "package.json"
git push origin --tags
All credits go to Andreas Mehlsen (@andreasbm) for the awesome logo design.
MIT © Frederik Wessberg (@FredWessberg) (Website)
Here's a full list of all possible feature
names.
Note that these will be deduplicated. For example, if you request es.object
, but also request es
, es.object
will only be included once as part of es
.
And, if you request performance.now
, date.now
will also be included since the polyfill depends on it. You don't have to worry about dependencies.
Bold-formatted polyfills are aliases for one or several other related feature
s.
formdata
form-data
requestidlecallback
request-idle-callback
requestanimationframe
request-animation-frame
es
es.promise
es.object
es.function
es.array
es.array-buffer
es.string
es.data-view
es.regexp
es.number
es.math
es.date
es.symbol
es.collections
es.typed-array
es.reflect
es.global-this
es2015
es
es.promise
es.promise.constructor
es.promise.any
es.promise.all-settled
es.promise.finally
es.object
es.object.assign
es.object.create
es.object.define-getter
es.object.define-setter
es.object.entries
es.object.from-entries
es.object.get-own-property-descriptors
es.object.lookup-getter
es.object.lookup-setter
es.object.values
es.object.define-properties
es.object.define-property
es.object.freeze
es.object.get-own-property-descriptor
es.object.get-own-property-names
es.object.get-prototype-of
es.object.is-extensible
es.object.is-frozen
es.object.is-sealed
es.object.is
es.object.keys
es.object.prevent-extensions
es.object.seal
es.object.set-prototype-of
es.object.to-string
es.function
es.function.bind
es.function.name
es.array
es.array.concat
es.array.copy-within
es.array.every
es.array.flat
es.array.flat-map
es.array.fill
es.array.filter
es.array.find
es.array.find-index
es.array.for-each
es.array.from
es.array.includes
es.array.index-of
es.array.is-array
es.array.iterator
es.array.join
es.array.last-index-of
es.array.map
es.array.of
es.array.reduce
es.array.reduce-right
es.array.slice
es.array.some
es.array.sort
es.array.species
es.array.splice
es.array.at
es.array.find-last
es.array.find-last-index
es.array-buffer
es.array-buffer.constructor
es.array-buffer.is-view
es.array-buffer.slice
es.string
es.string.anchor
es.string.big
es.string.blink
es.string.bold
es.string.code-point-at
es.string.ends-with
es.string.fixed
es.string.fontcolor
es.string.fontsize
es.string.from-code-point
es.string.includes
es.string.italics
es.string.iterator
es.string.link
es.string.match
es.string.pad-end
es.string.pad-start
es.string.raw
es.string.repeat
es.string.search
es.string.small
es.string.split
es.string.starts-with
es.string.strike
es.string.sub
es.string.sup
es.string.trim
es.string.trim-start
es.string.trim-end
es.string.replace-all
es.string.match-all
es.string.at
es.regexp
es.regexp.constructor
es.regexp.flags
es.regexp.to-string
es.number
es.number.constructor
es.number.epsilon
es.number.is-finite
es.number.is-integer
es.number.is-nan
es.number.is-safe-integer
es.number.max-safe-integer
es.number.min-safe-integer
es.number.parse-float
es.number.parse-int
es.number.to-fixed
es.number.to-precision
es.math
es.math.acosh
es.math.asinh
es.math.atanh
es.math.cbrt
es.math.clz32
es.math.cosh
es.math.expm1
es.math.fround
es.math.hypot
es.math.imul
es.math.log1p
es.math.log2
es.math.log10
es.math.sign
es.math.sinh
es.math.tanh
es.math.trunc
es.date
es.date.now
es.date.to-iso-string
es.date.to-json
es.date.to-primitive
es.date.to-string
es.symbol
es.symbol.async-iterator
es.symbol.has-instance
es.symbol.is-concat-spreadable
es.symbol.iterator
es.symbol.constructor
es.symbol.match
es.symbol.match-all
es.symbol.replace
es.symbol.search
es.symbol.species
es.symbol.split
es.symbol.to-primitive
es.symbol.to-string-tag
es.symbol.unscopables
es.symbol.description
es.collections
es.map
es.weak-map
es.set
es.weak-set
es.typed-array
es.typed-array.copy-within
es.typed-array.every
es.typed-array.fill
es.typed-array.filter
es.typed-array.find
es.typed-array.find-index
es.typed-array.float32-array
es.typed-array.float64-array
es.typed-array.for-each
es.typed-array.from
es.typed-array.includes
es.typed-array.index-of
es.typed-array.int8-array
es.typed-array.int16-array
es.typed-array.int32-array
es.typed-array.iterator
es.typed-array.join
es.typed-array.last-index-of
es.typed-array.map
es.typed-array.of
es.typed-array.reduce
es.typed-array.reduce-right
es.typed-array.reverse
es.typed-array.set
es.typed-array.slice
es.typed-array.some
es.typed-array.sort
es.typed-array.subarray
es.typed-array.to-locale-string
es.typed-array.to-string
es.typed-array.uint8-array
es.typed-array.uint8-clamped-array
es.typed-array.uint16-array
es.typed-array.uint32-array
es.typed-array.at
es.typed-array.find-last
es.typed-array.find-last-index
es.reflect
es.reflect.apply
es.reflect.construct
es.reflect.define-property
es.reflect.delete-property
es.reflect.get
es.reflect.get-own-property-descriptor
es.reflect.get-prototype-of
es.reflect.has
es.reflect.is-extensible
es.reflect.own-keys
es.reflect.prevent-extensions
es.reflect.set
es.reflect.set-prototype-of
dom.collections.iterable
dom.collections.iterator
dom.collections.for-each
intl
intl.date-time-format
intl.display-names
intl.get-canonical-locales
intl.list-format
intl.locale
intl.number-format
intl.plural-rules
intl.relative-time-format
animation
web-animations
web-components
custom-elements
shadow-dom
template
event
event.constructor
event.focusin
event.hashchange
setimmediate
set-immediate
globalthis
es.global-this
global-this
es.global-this
adopted-style-sheets
constructable-style-sheets
structuredclone
structured-clone
base64
atob
btoa
systemjs
zone
performance.now
url
object-fit
console
blob
proxy
es.string.replace
pointer-event
xhr
fetch
regenerator-runtime
queryselector
document-fragment
node.parentelement
scroll-behavior
focus-visible
node.contains
window
document
class-list
dom-token-list
element
custom-event
event-source
get-computed-style
intersection-observer
mutation-observer
resize-observer
broadcast-channel
proto