const arr = [1, 2, 3]
let transformed = []
if (arr.includes('babel')) {
transformed = arr.map(num => num * num)
}
"use strict";
var arr = [1, 2, 3];
var transformed = null;
if (arr.includes("babel")) {
transformed = arr.map(function(num) {
return num * num;
});
}
npm install --save @babel/polyfill
import "@babel/polyfill";
module.exports = {
entry: ["@babel/polyfill", "./app.js"],
};
// Cover all standardized ES6 APIs.
import "core-js/es6";
// Standard now
import "core-js/fn/array/includes";
import "core-js/fn/string/pad-start";
import "core-js/fn/string/pad-end";
import "core-js/fn/symbol/async-iterator";
import "core-js/fn/object/get-own-property-descriptors";
import "core-js/fn/object/values";
import "core-js/fn/object/entries";
import "core-js/fn/promise/finally";
// Ensure that we polyfill ES6 compat for anything web-related, if it exists.
import "core-js/web";
import "regenerator-runtime/runtime";
...
import 'core-js';
import 'core-js/modules/es.promise.finally';
import 'core-js/modules/es.string.pad-start';
import 'core-js/modules/es.string.pad-end';
...
// first file:
var set = new Set();
// second file:
var array = Array.of(1, 2, 3);
original source
// first file:
import 'core-js/modules/es.set';
var set = new Set();
// second file:
import 'core-js/modules/es.array.of';
var array = Array.of(1, 2, 3);
compiled source
import 'element-closest'
import 'core-js/es6/promise'
...
<script
src="https://cdn.polyfill.io/v2/polyfill.min.js">
</script>
/* Polyfill service v3.25.1
* For detailed credits and licence information see https://github.com/financial-times/polyfill-service.
*
* UA detected: chrome/69.0.0
* Features requested: default
* */
(function(undefined) {
/* No polyfills found for current settings */
})
.call('object' === typeof window && window ||
'object' === typeof self && self ||
'object' === typeof global && global ||
{});
/* Polyfill service v3.25.1
* For detailed credits and licence information see https://github.com/financial-times/polyfill-service.
*
* UA detected: ie/11.0.0
* Features requested: default
*
* - Object.assign,
* - Symbol,
* - Symbol.iterator
* - Symbol.toStringTag
* - _Iterator
* - Object.setPrototypeOf
* - String.prototype.includes
* - String.prototype.contains
* - _ArrayIterator
...
https://cdn.polyfill.io/v2/polyfill.min.js
"default":
[
"Array.from","Array.isArray","Array.of","Array.prototype.every",
"Array.prototype.fill","Array.prototype.filter","Array.prototype.forEach",
"Array.prototype.indexOf","Array.prototype.lastIndexOf",
"Array.prototype.map","Array.prototype.reduce",
"Array.prototype.reduceRight","Array.prototype.some",
....
]
https://cdn.polyfill.io/v2/polyfill.min.js
?features=fetch,IntersectionObserver
&excludes=Document
https://cdn.polyfill.io/v2/polyfill.min.js
?features=fetch,IntersectionObserver&
flags=always,gated
https://cdn.polyfill.io/v2/polyfill.min.js
?features=fetch,IntersectionObserver&
ua=Mozilla%2F5.0%20(Linux%3B%20
Android%206.0.1%3B%20SM-N910S%20Build%2FMMB29K)%20
AppleWebKit%2F537.36%20(KHTML%2C%20like%20Gecko)%20
Chrome%2F50.0.2661.102%20Crosswalk%2F20.50.533.55%20
Mobile%20Safari%2F537.36%20NAVER
(inapp%3B%20search%3B%20590%3B%208.8.2)
https://cdn.polyfill.io/v2/polyfill.min.js
?features=IntersectionObserver&
unknown=polyfill
var features = [];
('Promise' in window) || features.push('Promise');
('IntersectionObserver' in window) ||
features.push('IntersectionObserver');
if (features.length) {
document.write
('<script src="https://cdn.polyfill.io/v2/polyfill.min.js?
unknown=polyfill&features='
+ features.join(',') + '&flags=gated,always">
<\x2fscript>')
}
{
default:
["Array.from",
"Array.of",
...
]
es6:
["Symbol.species",
...
]
...
}
polyfills/__dist/aliases.json
{
"aliases": [
],
"browsers": {
"android": "4.4 - *",
...
},
"dependencies": [
"getComputedStyle",
...
]
}
config.json for each polyfill lib
$ tsort <<EOF
> 3 8
> 3 10
> 5 11
> 7 8
> 7 11
> 8 9
> 11 2
> 11 9
> 11 10
> EOF
//output
7 5 3 11 8 10 2 9
Text
sudo apt-get install nginx-module-njs
load_module modules/ngx_http_js_module-debug.so
load_module modules/ngx_http_js_module.so
develop
production
js_include conf.d/normalize.js;
js_set $ua normalizeUserAgent;
...
location / {
...
proxy_cache_key $scheme$proxy_host$request_uri$ua;
...
}
/etc/nginx/conf.d/default.conf
...
UA.normalize = function(uaString) {
if (uaString.match(/^\w+\/\d+(\.\d+(\.\d+)?)?$/i)) {
return uaString.toLowerCase();
}
var ua = new UA(uaString);
return ua.getFamily() + '/' + ua.getVersion();
};
function normalizeUserAgent(req) {
return UA.normalize(req.headers['user-agent']);
}
const port = process.env.PORT || 3000
...
startService(port, (err, app) => {
....
if (!Number.isInteger(port) && port.startsWith('/')) {
fs.chmodSync(port, '777')
}
...
})
/bin/polyfill-service
CMD ["pm2-runtime", "-i", "max", "bin/polyfill-service"]
/bin/polyfill-service
const baseLineVersions = {
"ie": ">=7",
"ie_mob": ">=8",
"chrome": "*",
"safari": ">=4",
"ios_saf": ">=4",
"ios_chr": ">=4",
"firefox": ">=3.6",
"firefox_mob": ">=4",
"android": ">=3",
"opera": ">=11",
"op_mob": ">=10",
"op_mini": ">=5",
"bb": ">=6",
"samsung_mob": ">=4"
};
// lib/index.js
const unsupportedUA = ((!ua.meetsBaseline() ||
ua.isUnknown()) && options.unknown !== 'polyfill');
// lib/UA.js
UA.prototype.meetsBaseline = function() {
return (this.ua.satisfies(
baseLineVersions[this.ua.family]));
};
UA.prototype.isUnknown = function() {
return (Object.keys(baseLineVersions).indexOf(
this.ua.family) === -1) ||
!this.meetsBaseline();
};
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?
features=IntersectionObserverEntry&flags=gated&unknown=polyfill"></script>
<script>
var features = [];
('IntersectionObserver' in window &&
'isIntersecting' in
window.IntersectionObserverEntry.prototype) ||
features.push('IntersectionObserverEntry');
if (features.length) {
document.write(
'<script src="https://cdn.polyfill.io/v2/polyfill.min.js' +
'/v2/polyfill.min.js?ua=chrome/50&features=' +
features.join(',') +
'&flags=gated,always'
<\x2fscript>')
}
</script>
const through = require('through2');
module.exports = {
module: {
rules: [
{
test: /\.ext$/,
loader: 'transform-loader?0',
options: {
transforms: [
function transform() {
return through(
(buffer) => {
const result = buffer.split('')
.map((chunk) => String.fromCharCode(127 - chunk.charCodeAt(0)));
return this.queue(result).join('');
},
() => this.queue(null)
);
}
]
...
Sample doesn't work
...
rules : [
{
test : /\.js$/,
loader: "transform-loader?0"
}
],
plugins : [
new webpack.LoaderOptionsPlugin({
options : {
transforms : [
function(file) {
return through(function(buf) {
....
}
]
}
})
]
It works
transforms : [
function(file) {
let chunks = [];
return through((buf, encoding, next) => {
chunks.push(buf.toString('utf8'))
next();
}, function(next) {
let transformed = transform(chunks.join(''));
this.push(transformed)
next()
});
...
]
It works
transforms : [
function(file) {
let chunks = [];
return through((buf, encoding, next) => {
chunks.push(buf.toString('utf8'))
next();
}, function(next) {
let transformed = transform(chunks.join(''));
this.push(transformed)
next()
});
...
]
module.exports = function updater() {
try {
require('./lib/update').update(function updating(err, results) {
if (err) {
...
return;
}
...
});
} catch (e) {
...
}
};
var LRU = require('lru-cache')(5000);
exports.lookup = function lookup(userAgent, jsAgent) {
var key = (userAgent || '')+(jsAgent || '')
, cached = LRU.get(key);
if (cached) return cached;
LRU.set(key, (
cached = exports.parse(userAgent, jsAgent)
));
return cached;
};
function transform(source, options = {}) {
const occurences = []
let f = falafel(source, options, node => {
if (node.type === 'Identifier' &&
['updater', 'lookup'].includes(node.name)) {
let targetNode = node
while (targetNode.type !== 'ExpressionStatement') {
targetNode = targetNode.parent;
}
occurences.push(targetNode);
}
});
occurences.forEach(occurence => {
occurence.update('')
})
return String(f)
}
//webpack.config
module.exports = {
...
externals: /(lru-cache|\.\/lib\/update)/,
...
}