Skip to content

Commit

Permalink
feat(@schematics/angular): evergreen new applications
Browse files Browse the repository at this point in the history
By default, we now generate new applications which support only evergreen browsers, as a result differential loading is now opt-in.

A new flag `--legacy-browsers`, was added to generate applications which support non evergreen browsers such as Internet Explorer 11.

**Note**: After an application is generated opting in and out of differential loading is still possible through the supported browsers configuration in the browserslist configuration file  defaulted to `.browserslistrc`.
  • Loading branch information
alan-agius4 authored and dgp1130 committed May 4, 2020
1 parent e2eed2c commit a723af4
Show file tree
Hide file tree
Showing 44 changed files with 295 additions and 351 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe('BuildBrowserFeatures', () => {
afterEach(async () => host.restore().toPromise());

describe('isDifferentialLoadingNeeded', () => {
it('should be true for for IE 9-11 and ES2015', () => {
it('should be true for IE 9-11 and ES2015', () => {
host.writeMultipleFiles({
'.browserslistrc': 'IE 9-11',
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries

# For the full list of supported browsers by the Angular framework, please see:
# https://angular.io/guide/browser-support

# You can see what browsers were selected by your queries by running:
# npx browserslist

> 0.5%
last 2 versions
Firefox ESR
not dead
not IE 9-11 # For IE 9-11 support, remove 'not'.
last 1 Chrome version
last 1 Firefox version
last 2 Edge major versions
last 2 Safari major version
last 2 iOS major versions
Firefox ESR<% if (legacyBrowsers) { %>
IE 9-11<% } else { %>
not IE 9-11 # For IE 9-11 support, remove 'not'.<% } %>
17 changes: 17 additions & 0 deletions packages/schematics/angular/application/index_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -401,4 +401,21 @@ describe('Application Schematic', () => {
expect(specTsConfig.extends).toEqual('../tsconfig.json');
});
});

it(`should add support for IE 9-11 in '.browserslistrc' when 'legacyBrowsers' is true`, async () => {
const options: ApplicationOptions = { ...defaultOptions, legacyBrowsers: true };
const tree = await schematicRunner.runSchematicAsync('application', options, workspaceTree)
.toPromise();
const content = tree.readContent('/projects/foo/.browserslistrc');
expect(content).not.toContain(`not IE 9-11 # For IE 9-11 support, remove 'not'.`);
expect(content).toContain('IE 9-11');
});

it(`should not add support for IE 9-11 in '.browserslistrc' when 'legacyBrowsers' is false`, async () => {
const options: ApplicationOptions = { ...defaultOptions, legacyBrowsers: false };
const tree = await schematicRunner.runSchematicAsync('application', options, workspaceTree)
.toPromise();
const content = tree.readContent('/projects/foo/.browserslistrc');
expect(content).toContain(`not IE 9-11 # For IE 9-11 support, remove 'not'.`);
});
});
5 changes: 5 additions & 0 deletions packages/schematics/angular/application/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@
"default": false,
"description": "When true, applies lint fixes after generating the application.",
"x-user-analytics": 15
},
"legacyBrowsers": {
"type": "boolean",
"description": "Add support for legacy browsers like Internet Explorer using differential loading.",
"default": false
}
},
"required": [
Expand Down
1 change: 1 addition & 0 deletions packages/schematics/angular/ng-new/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export default function(options: NgNewOptions): Rule {
// always 'skipInstall' here, so that we do it after the move
skipInstall: true,
minimal: options.minimal,
legacyBrowsers: options.legacyBrowsers,
};

return chain([
Expand Down
5 changes: 5 additions & 0 deletions packages/schematics/angular/ng-new/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@
"type": "boolean",
"default": false
},
"legacyBrowsers": {
"type": "boolean",
"description": "Add support for legacy browsers like Internet Explorer using differential loading.",
"default": false
},
"packageManager": {
"description": "The package manager used to install dependencies.",
"type": "string",
Expand Down
8 changes: 2 additions & 6 deletions tests/legacy-cli/e2e/tests/basic/aot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,10 @@ export default async function () {
await ng('build', '--aot=true');

if (getGlobalVariable('argv')['ve']) {
await expectFileToMatch('dist/test-project/main-es5.js',
/platformBrowser.*bootstrapModuleFactory.*AppModuleNgFactory/);
await expectFileToMatch('dist/test-project/main-es2015.js',
await expectFileToMatch('dist/test-project/main.js',
/platformBrowser.*bootstrapModuleFactory.*AppModuleNgFactory/);
} else {
await expectFileToMatch('dist/test-project/main-es5.js',
/platformBrowser.*bootstrapModule.*AppModule/);
await expectFileToMatch('dist/test-project/main-es2015.js',
await expectFileToMatch('dist/test-project/main.js',
/platformBrowser.*bootstrapModule.*AppModule/);
}
}
6 changes: 2 additions & 4 deletions tests/legacy-cli/e2e/tests/basic/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import { ng } from '../../utils/process';
export default async function() {
// Development build
await ng('build');
await expectFileToMatch('dist/test-project/index.html', 'main-es5.js');
await expectFileToMatch('dist/test-project/index.html', 'main-es2015.js');
await expectFileToMatch('dist/test-project/index.html', 'main.js');

// Named Development build
await ng('build', 'test-project');
Expand All @@ -15,7 +14,6 @@ export default async function() {

// Production build
await ng('build', '--prod');
await expectFileToMatch('dist/test-project/index.html', /main-es2015\.[a-zA-Z0-9]{20}\.js/);
await expectFileToMatch('dist/test-project/index.html', /main-es5\.[a-zA-Z0-9]{20}\.js/);
await expectFileToMatch('dist/test-project/index.html', /main\.[a-zA-Z0-9]{20}\.js/);
await ng('build', '--prod', '--no-progress', 'test-project');
}
49 changes: 11 additions & 38 deletions tests/legacy-cli/e2e/tests/basic/scripts-array.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// TODO(architect): edit the architect config instead of the cli config.

import { oneLineTrim } from 'common-tags';
import { appendToFile, expectFileToMatch, writeMultipleFiles } from '../../utils/fs';
import { ng } from '../../utils/process';
Expand Down Expand Up @@ -53,40 +51,15 @@ export default async function () {
await expectFileToMatch('dist/test-project/renamed-lazy-script.js', 'pre-rename-lazy-script');

// index.html lists the right bundles
if (process.env['NG_BUILD_DIFFERENTIAL_FULL']) {
await expectFileToMatch(
'dist/test-project/index.html',
oneLineTrim`
<script src="runtime-es2015.js" type="module"></script>
<script src="polyfills-es2015.js" type="module"></script>
<script src="runtime-es5.js" nomodule defer></script>
<script src="polyfills-es5.js" nomodule defer></script>
<script src="scripts.js" defer></script>
<script src="renamed-script.js" defer></script>
<script src="vendor-es2015.js" type="module"></script>
<script src="main-es2015.js" type="module"></script>
<script src="vendor-es5.js" nomodule defer></script>
<script src="main-es5.js" nomodule defer></script>
`,
);
} else {
await expectFileToMatch(
'dist/test-project/index.html',
oneLineTrim`
<script src="runtime-es2015.js" type="module"></script>
<script src="runtime-es5.js" nomodule defer></script>
<script src="polyfills-es5.js" nomodule defer></script>
<script src="polyfills-es2015.js" type="module"></script>
<script src="scripts.js" defer></script>
<script src="renamed-script.js" defer></script>
<script src="vendor-es2015.js" type="module"></script>
<script src="vendor-es5.js" nomodule defer></script>
<script src="main-es2015.js" type="module"></script>
<script src="main-es5.js" nomodule defer></script>
`,
);
}
// Ensure scripts can be separately imported from the app.
await expectFileToMatch('dist/test-project/main-es5.js', /console\.log\((['"])string\-script\1\);/);
await expectFileToMatch('dist/test-project/main-es2015.js', /console\.log\((['"])string\-script\1\);/);
await expectFileToMatch(
'dist/test-project/index.html',
oneLineTrim`
<script src="runtime.js" defer></script>
<script src="polyfills.js" defer></script>
<script src="scripts.js" defer></script>
<script src="renamed-script.js" defer></script>
<script src="vendor.js" defer></script>
<script src="main.js" defer></script>
`,
);
}
31 changes: 0 additions & 31 deletions tests/legacy-cli/e2e/tests/basic/styles-array.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// TODO(architect): edit the architect config instead of the cli config.
import { oneLineTrim } from 'common-tags';
import { expectFileToMatch, writeMultipleFiles } from '../../utils/fs';
import { ng } from '../../utils/process';
Expand Down Expand Up @@ -42,34 +41,4 @@ export default async function() {
<link rel="stylesheet" href="renamed-style.css">
`,
);

if (process.env['NG_BUILD_DIFFERENTIAL_FULL']) {
await expectFileToMatch(
'dist/test-project/index.html',
oneLineTrim`
<script src="runtime-es2015.js" type="module"></script>
<script src="polyfills-es2015.js" type="module"></script>
<script src="runtime-es5.js" nomodule defer></script>
<script src="polyfills-es5.js" nomodule defer></script>
<script src="vendor-es2015.js" type="module"></script>
<script src="main-es2015.js" type="module"></script>
<script src="vendor-es5.js" nomodule defer></script>
<script src="main-es5.js" nomodule defer></script>
`,
);
} else {
await expectFileToMatch(
'dist/test-project/index.html',
oneLineTrim`
<script src="runtime-es2015.js" type="module"></script>
<script src="runtime-es5.js" nomodule defer></script>
<script src="polyfills-es5.js" nomodule defer></script>
<script src="polyfills-es2015.js" type="module"></script>
<script src="vendor-es2015.js" type="module"></script>
<script src="vendor-es5.js" nomodule defer></script>
<script src="main-es2015.js" type="module"></script>
<script src="main-es5.js" nomodule defer></script>
`,
);
}
}
22 changes: 11 additions & 11 deletions tests/legacy-cli/e2e/tests/build/css-urls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ export default function () {
/url\('\/assets\/global-img-absolute\.svg'\)/))
.then(() => expectFileToMatch('dist/test-project/styles.css',
/global-img-relative\.png/))
.then(() => expectFileToMatch('dist/test-project/main-es5.js',
.then(() => expectFileToMatch('dist/test-project/main.js',
'/assets/component-img-absolute.svg'))
.then(() => expectFileToMatch('dist/test-project/main-es5.js',
.then(() => expectFileToMatch('dist/test-project/main.js',
/component-img-relative\.png/))
// Check files are correctly created.
.then(() => expectToFail(() => expectFileToExist('dist/test-project/global-img-absolute.svg')))
Expand All @@ -52,21 +52,21 @@ export default function () {
'--extract-css'))
.then(() => expectFileToMatch('dist/test-project/styles.css',
/url\(\'\/assets\/global-img-absolute\.svg\'\)/))
.then(() => expectFileToMatch('dist/test-project/main-es5.js',
.then(() => expectFileToMatch('dist/test-project/main.js',
/url\(\'\/assets\/component-img-absolute\.svg\'\)/))
// Check urls with base-href scheme are used as is (with deploy-url).
.then(() => ng('build', '--base-href=http://base.url/', '--deploy-url=deploy/',
'--extract-css'))
.then(() => expectFileToMatch('dist/test-project/styles.css',
/url\(\'\/assets\/global-img-absolute\.svg\'\)/))
.then(() => expectFileToMatch('dist/test-project/main-es5.js',
.then(() => expectFileToMatch('dist/test-project/main.js',
/url\(\'\/assets\/component-img-absolute\.svg\'\)/))
// Check urls with deploy-url and base-href scheme only use deploy-url.
.then(() => ng('build', '--base-href=http://base.url/', '--deploy-url=http://deploy.url/',
'--extract-css'))
.then(() => expectFileToMatch('dist/test-project/styles.css',
/url\(\'\/assets\/global-img-absolute\.svg\'\)/))
.then(() => expectFileToMatch('dist/test-project/main-es5.js',
.then(() => expectFileToMatch('dist/test-project/main.js',
/url\(\'\/assets\/component-img-absolute\.svg\'\)/))
// Check with base-href and deploy-url flags.
.then(() => ng('build', '--base-href=/base/', '--deploy-url=deploy/',
Expand All @@ -75,9 +75,9 @@ export default function () {
'/assets/global-img-absolute.svg'))
.then(() => expectFileToMatch('dist/test-project/styles.css',
/global-img-relative\.png/))
.then(() => expectFileToMatch('dist/test-project/main-es5.js',
.then(() => expectFileToMatch('dist/test-project/main.js',
'/assets/component-img-absolute.svg'))
.then(() => expectFileToMatch('dist/test-project/main-es5.js',
.then(() => expectFileToMatch('dist/test-project/main.js',
/deploy\/component-img-relative\.png/))
// Check with identical base-href and deploy-url flags.
.then(() => ng('build', '--base-href=/base/', '--deploy-url=/base/',
Expand All @@ -86,9 +86,9 @@ export default function () {
'/assets/global-img-absolute.svg'))
.then(() => expectFileToMatch('dist/test-project/styles.css',
/global-img-relative\.png/))
.then(() => expectFileToMatch('dist/test-project/main-es5.js',
.then(() => expectFileToMatch('dist/test-project/main.js',
'/assets/component-img-absolute.svg'))
.then(() => expectFileToMatch('dist/test-project/main-es5.js',
.then(() => expectFileToMatch('dist/test-project/main.js',
/\/base\/component-img-relative\.png/))
// Check with only base-href flag.
.then(() => ng('build', '--base-href=/base/',
Expand All @@ -97,8 +97,8 @@ export default function () {
'/assets/global-img-absolute.svg'))
.then(() => expectFileToMatch('dist/test-project/styles.css',
/global-img-relative\.png/))
.then(() => expectFileToMatch('dist/test-project/main-es5.js',
.then(() => expectFileToMatch('dist/test-project/main.js',
'/assets/component-img-absolute.svg'))
.then(() => expectFileToMatch('dist/test-project/main-es5.js',
.then(() => expectFileToMatch('dist/test-project/main.js',
/component-img-relative\.png/));
}
15 changes: 4 additions & 11 deletions tests/legacy-cli/e2e/tests/build/deploy-url.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { ng } from '../../utils/process';
import { copyProjectAsset } from '../../utils/assets';
import { expectFileToMatch, writeMultipleFiles } from '../../utils/fs';
import { updateJsonFile } from '../../utils/project';
import { getGlobalVariable } from '../../utils/env';


export default function () {
return Promise.resolve()
Expand All @@ -13,20 +10,16 @@ export default function () {
// use image with file size >10KB to prevent inlining
.then(() => copyProjectAsset('images/spectrum.png', './src/assets/more.png'))
.then(() => ng('build', '--deploy-url=deployUrl/', '--extract-css'))
.then(() => expectFileToMatch('dist/test-project/index.html', 'deployUrl/main-es5.js'))
.then(() => expectFileToMatch('dist/test-project/index.html', 'deployUrl/main.js'))
// verify --deploy-url isn't applied to extracted css urls
.then(() => expectFileToMatch('dist/test-project/styles.css',
/url\(['"]?more\.png['"]?\)/))
.then(() => ng('build', '--deploy-url=http://example.com/some/path/', '--extract-css'))
.then(() => expectFileToMatch('dist/test-project/index.html', 'http://example.com/some/path/main-es5.js'))
.then(() => expectFileToMatch('dist/test-project/index.html', 'http://example.com/some/path/main.js'))
// verify --deploy-url is applied to non-extracted css urls
.then(() => ng('build', '--deploy-url=deployUrl/', '--extract-css=false'))
.then(() => expectFileToMatch('dist/test-project/styles-es5.js',
.then(() => expectFileToMatch('dist/test-project/styles.js',
/\(['"]?deployUrl\/more\.png['"]?\)/))
.then(() => expectFileToMatch('dist/test-project/runtime-es5.js',
.then(() => expectFileToMatch('dist/test-project/runtime.js',
/__webpack_require__\.p\s*=\s*"deployUrl\/";/));
// // verify slash is appended to the end of --deploy-url if missing
// .then(() => ng('build', '--deploy-url=deployUrl', '--extract-css=false'))
// .then(() =>
// expectFileToMatch('dist/test-project/untime.js', /__webpack_require__\.p = "deployUrl\/";/));
}
9 changes: 8 additions & 1 deletion tests/legacy-cli/e2e/tests/build/differential-cache.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as crypto from 'crypto';
import * as fs from 'fs';
import { rimraf } from '../../utils/fs';
import { rimraf, replaceInFile } from '../../utils/fs';
import { ng } from '../../utils/process';

function generateFileHashMap(): Map<string, string> {
Expand Down Expand Up @@ -39,6 +39,13 @@ export default async function() {
let oldHashes: Map<string, string>;
let newHashes: Map<string, string>;

// Enable Differential loading to run both size checks
await replaceInFile(
'.browserslistrc',
'not IE 9-11',
'IE 9-11',
);

// Remove the cache so that an initial build and build with cache can be tested
await rimraf('./node_modules/.cache');

Expand Down
49 changes: 49 additions & 0 deletions tests/legacy-cli/e2e/tests/build/differential-loading.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { oneLineTrim } from 'common-tags';
import { appendToFile, expectFileToMatch, replaceInFile, writeMultipleFiles } from '../../utils/fs';
import { ng } from '../../utils/process';
import { updateJsonFile } from '../../utils/project';
import { expectToFail } from '../../utils/utils';

export default async function () {
// Enable Differential loading to run both size checks
await replaceInFile(
'.browserslistrc',
'not IE 9-11',
'IE 9-11',
);

await writeMultipleFiles({
'src/string-script.js': "console.log('string-script'); var number = 1+1;",
'src/pre-rename-script.js': "console.log('pre-rename-script');",
});

await updateJsonFile('angular.json', configJson => {
const appArchitect = configJson.projects['test-project'].architect;
appArchitect.build.options.scripts = [
{ input: 'src/string-script.js' },
{ input: 'src/pre-rename-script.js', bundleName: 'renamed-script' },
];
});

await ng('build', '--extract-css', '--vendor-chunk', '--optimization');

// index.html lists the right bundles
await expectFileToMatch(
'dist/test-project/index.html',
oneLineTrim`
<script src="runtime-es2015.js" type="module"></script>
<script src="runtime-es5.js" nomodule defer></script>
<script src="polyfills-es5.js" nomodule defer></script>
<script src="polyfills-es2015.js" type="module"></script>
<script src="scripts.js" defer></script>
<script src="renamed-script.js" defer></script>
<script src="vendor-es2015.js" type="module"></script>
<script src="vendor-es5.js" nomodule defer></script>
<script src="main-es2015.js" type="module"></script>
<script src="main-es5.js" nomodule defer></script>
`,
);

await expectFileToMatch('dist/test-project/vendor-es2015.js', /class \w{constructor\(/);
await expectToFail(() => expectFileToMatch('dist/test-project/vendor-es5.js', /class \w{constructor\(/));
}

0 comments on commit a723af4

Please sign in to comment.