Autopolyfiller — Precise polyfills
This is like Autoprefixer, but for JavaScript polyfills. It scans your code and applies only required polyfills. Live example.
Assume you code is Object.keys(window)
. Object.keys
polyfill is required to run it in any browser (include IE7). On the other hand this code can be executed on iOS 7 Safari without any polyfills. AutoPolyfiller knows about ES5 and ES6 features and their support in browsers. It can help you to write cutting-edge JavaScript without thinking about ES shims and shivs.
How it works. Step by step:
- Using AST matchers, it scans your code and finds all polyfills
- If target browsers are specified, then it reduces the list of polyfills according to the "feature database"
- It generates polyfills code, using polyfills database, which precisely fixes only required features
Limitations:
- Right now it supports only safe and cross-browser polyfills from ES5, but you can add your own (see examples).
- It can have a false-positives for some cases. For instance, autopolyfiller thinks that
$('div').map()
is call of Array.prototype.map
. But you can exclude false-positives (see examples).
It will not work if:
- You are
eval
ing code with polyfills. Eg eval('Object.keys(this)')
- You are doing something odd. Eg
Object['k' + 'eys']()
Installation
autopolyfiller
can be installed using npm
:
npm install autopolyfiller
CLI Example
$ autopolyfiller lib/**/*.js -b "Explorer 7, Chrome >= 10"
$ cat lib/*.js | autopolyfiller
Grunt, Gulp & Enb tasks
Example
require('autopolyfiller')().add(code) + code;
List of polyfills without browsers filtering
var autopolyfiller = require('autopolyfiller');
autopolyfiller()
.add('"".trim();')
.polyfills;
Filtering using Autoprefixer-style browser matchers
var autopolyfiller = require('autopolyfiller');
autopolyfiller('IE 11', 'Chrome >= 31')
.add('"".trim();Object.create();new Promise()')
.polyfills;
Default autoprefixer browsers
var autopolyfiller = require('autopolyfiller'),
autoprefixer = require('autopolyfiller');
autopolyfiller(autoprefixer.default)
.add('new Promise();')
.polyfills;
Excluding/including polyfills
var autopolyfiller = require('autopolyfiller');
autopolyfiller()
.exclude(['Promise'])
.include(['String.prototype.trim'])
.include(['Array.*'])
.add('new My.Promise();')
.polyfills;
Using custom parser
var autopolyfiller = require('autopolyfiller');
autopolyfiller()
.withParser('acorn@0.11.0', {ecmaVersion: 6})
.add('array.map(x => x * x)')
.polyfills;
Adding your own polyfills
var query = require('grasp-equery').query;
var autopolyfiller = require('autopolyfiller');
autopolyfiller.use({
test: function (ast) {
return query('Object.newFeature(_$)', ast).length > 0 ? ['Object.newFeature'] : [];
},
polyfill: {
'Object.newFeature': 'Object.newFeature = function () {};'
},
support: {
'Chrome': [{
only: '29',
fill: 'Object.newFeature'
}]
},
wrapper: {
'Object.newFeature': {
'before': 'if (!("newFeature" in Object)) {',
'after': '}'
}
}
});
autopolyfiller()
.add('Object.create();Object.newFeature();')
.polyfills;
autopolyfiller()
.add('Object.newFeature();')
.toString();
autopolyfiller('Chrome >= 20')
.add('Object.create();Object.newFeature();')
.polyfills;
Handling polyfills issues
Right now Autopolyfiller aggreagates existing sources of polyfills. If you have any issues related to a polyfill code itself, please, add an issue or a pull request to the jonathantneal/polyfill.
Here is how to temporary workaround, while your issue being resolved:
var autopolyfiller = require('autopolyfiller');
autopolyfiller.use({
polyfill: {
'Function.prototype.bind': 'fixed code (!Function.prototype.bind)'
}
});