Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not include polyfill if browser targets don't need it #173

Merged
merged 5 commits into from
Dec 19, 2018
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions assets/browser-fetch.js.t
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@

<%= moduleBody %>

if (!self.fetch) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error should be changed to provide more actionable info if we agree on changes below.

throw new Error('fetch is not defined - maybe your browser targets are not covering everything you need?');
}

var pending = 0;
function decrement(result) {
pending--;
Expand Down
40 changes: 35 additions & 5 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use strict';

const caniuse = require('caniuse-api');
const path = require('path');
// We use a few different Broccoli plugins to build our trees:
//
Expand Down Expand Up @@ -73,7 +74,10 @@ module.exports = {
importTarget = this;
}

app._fetchBuildConfig = app.options['ember-fetch'] || { preferNative: false };
const options = Object.assign({ preferNative: false, alwaysIncludePolyfill: true}, app.options['ember-fetch'] || {});
xg-wang marked this conversation as resolved.
Show resolved Hide resolved
options.browsers = this.project.targets && this.project.targets.browsers;

app._fetchBuildConfig = options;

importTarget.import('vendor/ember-fetch.js', {
exports: {
Expand Down Expand Up @@ -113,7 +117,8 @@ module.exports = {
}

const app = this._findApp();
const preferNative = app._fetchBuildConfig.preferNative;
const options = app._fetchBuildConfig;
xg-wang marked this conversation as resolved.
Show resolved Hide resolved
const preferNative = options.preferNative;

return debug(map(browserTree, (content) => `if (typeof FastBoot === 'undefined') {
var preferNative = ${preferNative};
Expand Down Expand Up @@ -144,6 +149,14 @@ module.exports = {
// wrapped in a shim that stops it from exporting a global and instead turns it into a module
// that can be used by the Ember app.
treeForBrowserFetch() {
const app = this._findApp();
xg-wang marked this conversation as resolved.
Show resolved Hide resolved
const options = app._fetchBuildConfig;
const browsers = options.browsers;
// To skip including the polyfill, you need to set `preferNative=true` AND `alwaysIncludePolyfill=false`
const alwaysIncludePolyfill = !options.preferNative || options.alwaysIncludePolyfill;
const needsFetchPolyfill = alwaysIncludePolyfill || !this._checkSupports('fetch', browsers);
const needsAbortControllerPolyfill = alwaysIncludePolyfill || !this._checkSupports('abortcontroller', browsers);

const abortcontrollerNode = debug(new Rollup(path.dirname(path.dirname(require.resolve('abortcontroller-polyfill'))), {
rollup: {
input: 'src/abortcontroller-polyfill.js',
Expand All @@ -167,19 +180,36 @@ module.exports = {
}
}), 'whatwg-fetch');

const polyfillNode = debug(concat(new MergeTrees([abortcontrollerNode, fetchNode]), {
inputFiles: ['abortcontroller.js', 'fetch.js'],
let inputNodes = [abortcontrollerNode, fetchNode];
let inputFiles = ['abortcontroller.js', 'fetch.js'];

if (!needsFetchPolyfill && needsAbortControllerPolyfill) {
inputNodes = [abortcontrollerNode];
inputFiles = ['abortcontroller.js'];
}

const polyfillNode = debug(concat(new MergeTrees(inputNodes), {
inputFiles,
outputFile: 'ember-fetch.js',
sourceMapConfig: { enabled: false }
}), 'after-concat');

return debug(new Template(polyfillNode, TEMPLATE_PATH, function(content) {
return {
moduleBody: content
moduleBody: needsFetchPolyfill || needsAbortControllerPolyfill ? content : ''
xg-wang marked this conversation as resolved.
Show resolved Hide resolved
};
}), 'browser-fetch');
},

_checkSupports(featureName, browsers) {
if (!browsers) {
return false;
}

let browserList = browsers.join(', ');
return caniuse.isSupported(featureName, browserList);
},

_findApp() {
if (typeof this._findHost === 'function') {
return this._findHost();
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"broccoli-stew": "^2.0.0",
"broccoli-templater": "^2.0.1",
"calculate-cache-key-for-tree": "^1.1.0",
"caniuse-api": "^3.0.0",
"ember-cli-babel": "^6.8.2",
"node-fetch": "^2.3.0",
"whatwg-fetch": "^3.0.0"
Expand Down
182 changes: 182 additions & 0 deletions test/browsers-target-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
'use strict';

const AddonFactory = require('../');
const expect = require('chai').expect;
const helpers = require('broccoli-test-helper');
const co = require('co');

describe(`Do not include the polyfill if the browser targets match`, function() {
xg-wang marked this conversation as resolved.
Show resolved Hide resolved
let output, subject, addon;

beforeEach(function() {
addon = Object.create(AddonFactory);
Object.assign(addon, {
addons: [],
_fetchBuildConfig: {
xg-wang marked this conversation as resolved.
Show resolved Hide resolved
preferNative: true,
browsers: ['last 1 chrome versions']
},
ui: {
writeWarnLine() {
}
}
});
subject = addon.treeForVendor();
output = helpers.createBuilder(subject);
});

afterEach(co.wrap(function* () {
yield output.dispose();
}));

it('preferNative is built into vendor file', co.wrap(function* () {
xg-wang marked this conversation as resolved.
Show resolved Hide resolved
yield output.build();
let files = output.read();
expect(files).to.have.all.keys('ember-fetch.js');
expect(files['ember-fetch.js']).to.include(`var preferNative = true`);
xg-wang marked this conversation as resolved.
Show resolved Hide resolved
expect(files['ember-fetch.js']).to.not.include(`fetch.polyfill = true`);
expect(files['ember-fetch.js']).to.not.include(`class AbortController`);
}));

});

describe(`Ignore target browsers if preferNative is false`, function() {
let output, subject, addon;

beforeEach(function() {
addon = Object.create(AddonFactory);
Object.assign(addon, {
addons: [],
_fetchBuildConfig: {
preferNative: false,
browsers: ['last 1 chrome versions']
},
ui: {
writeWarnLine() {
}
}
});
subject = addon.treeForVendor();
output = helpers.createBuilder(subject);
});

afterEach(co.wrap(function* () {
yield output.dispose();
}));

it('preferNative is built into vendor file', co.wrap(function* () {
yield output.build();
let files = output.read();
expect(files).to.have.all.keys('ember-fetch.js');
expect(files['ember-fetch.js']).to.include(`var preferNative = false`);
expect(files['ember-fetch.js']).to.include(`fetch.polyfill = true`);
expect(files['ember-fetch.js']).to.include(`class AbortController`);
}));

});

describe(`Include the polyfill if the browser targets do not match`, function() {
let output, subject, addon;

beforeEach(function() {
addon = Object.create(AddonFactory);
Object.assign(addon, {
addons: [],
_fetchBuildConfig: {
preferNative: true,
browsers: ['ie 11']
},
ui: {
writeWarnLine() {
}
}
});
subject = addon.treeForVendor();
output = helpers.createBuilder(subject);
});

afterEach(co.wrap(function* () {
yield output.dispose();
}));

it('preferNative is built into vendor file', co.wrap(function* () {
yield output.build();
let files = output.read();
expect(files).to.have.all.keys('ember-fetch.js');
expect(files['ember-fetch.js']).to.include(`var preferNative = true`);
expect(files['ember-fetch.js']).to.include(`fetch.polyfill = true`);
expect(files['ember-fetch.js']).to.include(`class AbortController`);
}));

});

describe(`Include the abortcontroller polyfill only if the browser targets support fetch only`, function() {
let output, subject, addon;

beforeEach(function() {
addon = Object.create(AddonFactory);
Object.assign(addon, {
addons: [],
_fetchBuildConfig: {
preferNative: true,
browsers: ['safari 11']
},
ui: {
writeWarnLine() {
}
}
});
subject = addon.treeForVendor();
output = helpers.createBuilder(subject);
});

afterEach(co.wrap(function* () {
yield output.dispose();
}));

it('preferNative is built into vendor file', co.wrap(function* () {
yield output.build();
let files = output.read();
expect(files).to.have.all.keys('ember-fetch.js');
expect(files['ember-fetch.js']).to.include(`var preferNative = true`);
expect(files['ember-fetch.js']).to.not.include(`fetch.polyfill = true`);
expect(files['ember-fetch.js']).to.include(`class AbortController`);
}));

});

describe(`Include the polyfill if alwaysIncludePolyfill=true`, function() {
let output, subject, addon;

beforeEach(function() {
addon = Object.create(AddonFactory);
Object.assign(addon, {
addons: [],
_fetchBuildConfig: {
preferNative: true,
alwaysIncludePolyfill: true,
browsers: ['last 1 chrome versions']
},
ui: {
writeWarnLine() {
}
}
});
subject = addon.treeForVendor();
output = helpers.createBuilder(subject);
});

afterEach(co.wrap(function* () {
yield output.dispose();
}));

it('preferNative is built into vendor file', co.wrap(function* () {
yield output.build();
let files = output.read();
expect(files).to.have.all.keys('ember-fetch.js');
expect(files['ember-fetch.js']).to.include(`var preferNative = true`);
expect(files['ember-fetch.js']).to.include(`fetch.polyfill = true`);
expect(files['ember-fetch.js']).to.include(`class AbortController`);
}));

});
54 changes: 37 additions & 17 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2224,14 +2224,14 @@ browserslist@^3.2.6:
caniuse-lite "^1.0.30000844"
electron-to-chromium "^1.3.47"

browserslist@^4.1.0:
version "4.3.4"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.3.4.tgz#4477b737db6a1b07077275b24791e680d4300425"
integrity sha512-u5iz+ijIMUlmV8blX82VGFrB9ecnUg5qEt55CMZ/YJEhha+d8qpBfOFuutJ6F/VKRXjZoD33b6uvarpPxcl3RA==
browserslist@^4.0.0, browserslist@^4.1.0:
version "4.3.6"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.3.6.tgz#0f9d9081afc66b36f477c6bdf3813f784f42396a"
integrity sha512-kMGKs4BTzRWviZ8yru18xBpx+CyHG9eqgRbj9XbE3IMgtczf4aiA0Y1YCpVdvUieKGZ03kolSPXqTcscBCb9qw==
dependencies:
caniuse-lite "^1.0.30000899"
electron-to-chromium "^1.3.82"
node-releases "^1.0.1"
caniuse-lite "^1.0.30000921"
electron-to-chromium "^1.3.92"
node-releases "^1.1.1"

bser@^2.0.0:
version "2.0.0"
Expand Down Expand Up @@ -2385,10 +2385,20 @@ can-symlink@^1.0.0:
dependencies:
tmp "0.0.28"

caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30000899:
version "1.0.30000907"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000907.tgz#0b9899bde53fb1c30e214fb12402361e02ff5c42"
integrity sha512-No5sQ/OB2Nmka8MNOOM6nJx+Hxt6MQ6h7t7kgJFu9oTuwjykyKRSBP/+i/QAyFHxeHB+ddE0Da1CG5ihx9oehQ==
caniuse-api@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0"
integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==
dependencies:
browserslist "^4.0.0"
caniuse-lite "^1.0.0"
lodash.memoize "^4.1.2"
lodash.uniq "^4.5.0"

caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30000921:
version "1.0.30000921"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000921.tgz#7a607c1623444b22351d834e093aedda3c42fbe8"
integrity sha512-Bu09ciy0lMWLgpYC77I0YGuI8eFRBPPzaSOYJK1jTI64txCphYCqnWbxJYjHABYVt/TYX/p3jNjLBR87u1Bfpw==

capture-exit@^1.2.0:
version "1.2.0"
Expand Down Expand Up @@ -3113,11 +3123,16 @@ ee-first@1.1.1:
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=

electron-to-chromium@^1.3.47, electron-to-chromium@^1.3.82:
electron-to-chromium@^1.3.47:
version "1.3.84"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.84.tgz#2e55df59e818f150a9f61b53471ebf4f0feecc65"
integrity sha512-IYhbzJYOopiTaNWMBp7RjbecUBsbnbDneOP86f3qvS0G0xfzwNSvMJpTrvi5/Y1gU7tg2NAgeg8a8rCYvW9Whw==

electron-to-chromium@^1.3.92:
version "1.3.92"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.92.tgz#9027b5abaea400045edd652c0e4838675c814399"
integrity sha512-En051LMzMl3/asMWGZEtU808HOoVWIpmmZx1Ep8N+TT9e7z/X8RcLeBU2kLSNLGQ+5SuKELzMx+MVuTBXk6Q9w==

ember-assign-polyfill@~2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/ember-assign-polyfill/-/ember-assign-polyfill-2.4.0.tgz#acb00466f7d674b3e6b030acfe255b3b1f6472e1"
Expand Down Expand Up @@ -6138,6 +6153,11 @@ lodash.keys@~2.3.0:
lodash._shimkeys "~2.3.0"
lodash.isobject "~2.3.0"

lodash.memoize@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=

lodash.merge@^4.3.1, lodash.merge@^4.6.0:
version "4.6.1"
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.1.tgz#adc25d9cb99b9391c59624f379fbba60d7111d54"
Expand Down Expand Up @@ -6201,7 +6221,7 @@ lodash.templatesettings@~2.3.0:
lodash._reinterpolate "~2.3.0"
lodash.escape "~2.3.0"

lodash.uniq@^4.2.0:
lodash.uniq@^4.2.0, lodash.uniq@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
Expand Down Expand Up @@ -6790,10 +6810,10 @@ node-pre-gyp@^0.10.0:
semver "^5.3.0"
tar "^4"

node-releases@^1.0.1:
version "1.0.3"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.0.3.tgz#3414ed84595096459c251699bfcb47d88324a9e4"
integrity sha512-ZaZWMsbuDcetpHmYeKWPO6e63pSXLb50M7lJgCbcM2nC/nQC3daNifmtp5a2kp7EWwYfhuvH6zLPWkrF8IiDdw==
node-releases@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.1.tgz#8fff8aea1cfcad1fb4205f805149054fbf73cafd"
integrity sha512-2UXrBr6gvaebo5TNF84C66qyJJ6r0kxBObgZIDX3D3/mt1ADKiHux3NJPWisq0wxvJJdkjECH+9IIKYViKj71Q==
dependencies:
semver "^5.3.0"

Expand Down