diff --git a/package.json b/package.json index 751520b3b9f9..d75a1a20d005 100644 --- a/package.json +++ b/package.json @@ -88,7 +88,7 @@ "@bazel/typescript": "~0.26.0", "@ngtools/json-schema": "^1.1.0", "@types/browserslist": "^4.4.0", - "@types/caniuse-api": "^3.0.0", + "@types/caniuse-lite": "^1.0.0", "@types/copy-webpack-plugin": "^4.4.1", "@types/express": "^4.16.0", "@types/glob": "^7.0.0", diff --git a/packages/angular_devkit/build_angular/package.json b/packages/angular_devkit/build_angular/package.json index 1803c7f40286..3b7cb6710da9 100644 --- a/packages/angular_devkit/build_angular/package.json +++ b/packages/angular_devkit/build_angular/package.json @@ -15,7 +15,7 @@ "ajv": "6.10.0", "autoprefixer": "9.6.0", "browserslist": "4.6.2", - "caniuse-api": "3.0.0", + "caniuse-lite": "1.0.30000974", "circular-dependency-plugin": "5.0.2", "clean-css": "4.2.1", "copy-webpack-plugin": "5.0.3", diff --git a/packages/angular_devkit/build_angular/src/angular-cli-files/models/safari-nomodule.js b/packages/angular_devkit/build_angular/src/angular-cli-files/models/safari-nomodule.js index 89db355822ae..1d2dbd1436ff 100644 --- a/packages/angular_devkit/build_angular/src/angular-cli-files/models/safari-nomodule.js +++ b/packages/angular_devkit/build_angular/src/angular-cli-files/models/safari-nomodule.js @@ -1,22 +1,8 @@ -/** - * Safari 10.1 supports modules, but does not support the `nomodule` attribute - it will - * load - * - * Again: this will **not** prevent inline script, e.g.: - * . - * - * This workaround is possible because Safari supports the non-standard 'beforeload' event. - * This allows us to trap the module and nomodule load. - * - * Note also that `nomodule` is supported in later versions of Safari - it's just 10.1 that - * omits this attribute. - */ -(function() { +(function () { var check = document.createElement('script'); if (!('noModule' in check) && 'onbeforeload' in check) { var support = false; - document.addEventListener('beforeload', function(e) { + document.addEventListener('beforeload', function (e) { if (e.target === check) { support = true; } else if (!e.target.hasAttribute('nomodule') || !support) { @@ -30,4 +16,4 @@ document.head.appendChild(check); check.remove(); } -}()); \ No newline at end of file +}()); diff --git a/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/common.ts b/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/common.ts index 7e9402759b0c..ec8318348e78 100644 --- a/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/common.ts +++ b/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/common.ts @@ -18,8 +18,8 @@ import { debug, } from 'webpack'; import { RawSource } from 'webpack-sources'; -import { AssetPatternClass } from '../../../browser/schema'; -import { isEs5SupportNeeded } from '../../../utils/differential-loading'; +import { AssetPatternClass, ExtraEntryPoint } from '../../../browser/schema'; +import { BuildBrowserFeatures } from '../../../utils/build-browser-features'; import { BundleBudgetPlugin } from '../../plugins/bundle-budget'; import { CleanCssWebpackPlugin } from '../../plugins/cleancss-webpack-plugin'; import { NamedLazyChunksPlugin } from '../../plugins/named-chunks-plugin'; @@ -40,7 +40,7 @@ export const buildOptimizerLoader: string = g['_DevKitIsLocal'] // tslint:disable-next-line:no-big-function export function getCommonConfig(wco: WebpackConfigOptions): Configuration { - const { root, projectRoot, buildOptions } = wco; + const { root, projectRoot, buildOptions, tsConfig } = wco; const { styles: stylesOptimization, scripts: scriptsOptimization } = buildOptions.optimization; const { styles: stylesSourceMap, @@ -67,25 +67,39 @@ export function getCommonConfig(wco: WebpackConfigOptions): Configuration { } if (wco.buildOptions.platform !== 'server') { - const es5Polyfills = path.join(__dirname, '..', 'es5-polyfills.js'); - const es5JitPolyfills = path.join(__dirname, '..', 'es5-jit-polyfills.js'); - if (targetInFileName) { - // For differential loading we don't need to have 2 polyfill bundles - if (buildOptions.scriptTargetOverride === ScriptTarget.ES2015) { - entryPoints['polyfills'] = [path.join(__dirname, '..', 'safari-nomodule.js')]; - } else { - entryPoints['polyfills'] = [es5Polyfills]; - if (!buildOptions.aot) { - entryPoints['polyfills'].push(es5JitPolyfills); + const buildBrowserFeatures = new BuildBrowserFeatures( + projectRoot, + tsConfig.options.target || ScriptTarget.ES5, + ); + if ((buildOptions.scriptTargetOverride || tsConfig.options.target) === ScriptTarget.ES5) { + if (buildOptions.es5BrowserSupport || + ( + buildOptions.es5BrowserSupport === undefined && + buildBrowserFeatures.isEs5SupportNeeded() + ) + ) { + // The nomodule polyfill needs to be inject prior to any script and be + // outside of webpack compilation because otherwise webpack will cause the + // script to be wrapped in window["webpackJsonp"] which causes this to fail. + if (buildBrowserFeatures.isNoModulePolyfillNeeded()) { + const noModuleScript: ExtraEntryPoint = { + bundleName: 'polyfills-nomodule-es5', + input: path.join(__dirname, '..', 'safari-nomodule.js'), + }; + buildOptions.scripts = buildOptions.scripts + ? [...buildOptions.scripts, noModuleScript] + : [noModuleScript]; } - } - } else { - // For NON differential loading we want to have 2 polyfill bundles - if (buildOptions.es5BrowserSupport - || (buildOptions.es5BrowserSupport === undefined && isEs5SupportNeeded(projectRoot))) { - entryPoints['polyfills-es5'] = [es5Polyfills]; + + // For differential loading we don't need to generate a seperate polyfill file + // because they will be loaded exclusivly based on module and nomodule + const polyfillsChunkName = buildBrowserFeatures.isDifferentialLoadingNeeded() + ? 'polyfills' + : 'polyfills-es5'; + + entryPoints[polyfillsChunkName] = [path.join(__dirname, '..', 'es5-polyfills.js')]; if (!buildOptions.aot) { - entryPoints['polyfills-es5'].push(es5JitPolyfills); + entryPoints[polyfillsChunkName].push(path.join(__dirname, '..', 'es5-jit-polyfills.js')); } } } diff --git a/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/utils.ts b/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/utils.ts index 2262bde39378..e0afd2ad53ef 100644 --- a/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/utils.ts +++ b/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/utils.ts @@ -8,16 +8,11 @@ // tslint:disable // TODO: cleanup this file, it's copied as is from Angular CLI. -import * as path from 'path'; import { basename, normalize } from '@angular-devkit/core'; import { ExtraEntryPoint, ExtraEntryPointClass } from '../../../browser/schema'; import { SourceMapDevToolPlugin } from 'webpack'; import { ScriptTarget } from 'typescript'; -export const ngAppResolve = (resolvePath: string): string => { - return path.resolve(process.cwd(), resolvePath); -}; - export interface HashFormat { chunk: string; extract: string; diff --git a/packages/angular_devkit/build_angular/src/angular-cli-files/utilities/package-chunk-sort.ts b/packages/angular_devkit/build_angular/src/angular-cli-files/utilities/package-chunk-sort.ts index 5f45c58c7af5..3b2262575d70 100644 --- a/packages/angular_devkit/build_angular/src/angular-cli-files/utilities/package-chunk-sort.ts +++ b/packages/angular_devkit/build_angular/src/angular-cli-files/utilities/package-chunk-sort.ts @@ -26,6 +26,7 @@ export function generateEntryPoints( }; const entryPoints = [ + 'polyfills-nomodule-es5', 'polyfills-es5', 'polyfills', 'sw-register', diff --git a/packages/angular_devkit/build_angular/src/browser/index.ts b/packages/angular_devkit/build_angular/src/browser/index.ts index b5d75281ee68..76bb388e6295 100644 --- a/packages/angular_devkit/build_angular/src/browser/index.ts +++ b/packages/angular_devkit/build_angular/src/browser/index.ts @@ -57,7 +57,7 @@ import { statsWarningsToString, } from '../angular-cli-files/utilities/stats'; import { ExecutionTransformer } from '../transforms'; -import { deleteOutputDir, isEs5SupportNeeded } from '../utils'; +import { BuildBrowserFeatures, deleteOutputDir } from '../utils'; import { Version } from '../utils/version'; import { generateBrowserWebpackConfigFromContext } from '../utils/webpack-browser-config'; import { Schema as BrowserBuilderSchema } from './schema'; @@ -202,9 +202,13 @@ export function buildWebpackBrowser( const tsConfigPath = path.resolve(getSystemPath(workspace.root), options.tsConfig); const tsConfig = readTsconfig(tsConfigPath); - if (isEs5SupportNeeded(projectRoot) && - tsConfig.options.target !== ScriptTarget.ES5 && - tsConfig.options.target !== ScriptTarget.ES2015) { + const target = tsConfig.options.target || ScriptTarget.ES5; + const buildBrowserFeatures = new BuildBrowserFeatures( + getSystemPath(projectRoot), + target, + ); + + if (target > ScriptTarget.ES2015 && buildBrowserFeatures.isDifferentialLoadingNeeded()) { context.logger.warn(tags.stripIndent` WARNING: Using differential loading with targets ES5 and ES2016 or higher may cause problems. Browsers with support for ES2015 will load the ES2016+ scripts diff --git a/packages/angular_devkit/build_angular/src/utils/build-browser-features.ts b/packages/angular_devkit/build_angular/src/utils/build-browser-features.ts new file mode 100644 index 000000000000..cfd3e58dda4c --- /dev/null +++ b/packages/angular_devkit/build_angular/src/utils/build-browser-features.ts @@ -0,0 +1,87 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import * as browserslist from 'browserslist'; +import { feature, features } from 'caniuse-lite'; +import * as ts from 'typescript'; + +export class BuildBrowserFeatures { + private readonly _supportedBrowsers: string[]; + private readonly _es6TargetOrLater: boolean; + + constructor( + private projectRoot: string, + private scriptTarget: ts.ScriptTarget, + ) { + this._supportedBrowsers = browserslist(undefined, { path: this.projectRoot }); + this._es6TargetOrLater = this.scriptTarget > ts.ScriptTarget.ES5; + } + + /** + * True, when one or more browsers requires ES5 + * support and the scirpt target is ES2015 or greater. + */ + isDifferentialLoadingNeeded(): boolean { + return this._es6TargetOrLater && this.isEs5SupportNeeded(); + } + + /** + * True, when one or more browsers requires ES5 support + */ + isEs5SupportNeeded(): boolean { + return !this.isFeatureSupported('es6-module'); + } + + /** + * Safari 10.1 and iOS Safari 10.3 supports modules, + * but does not support the `nomodule` attribute. + * While return `true`, when support for Safari 10.1 and iOS Safari 10.3 + * is required and in differential loading is enabled. + */ + isNoModulePolyfillNeeded(): boolean { + if (!this.isDifferentialLoadingNeeded()) { + return false; + } + + const safariBrowsers = [ + 'safari 10.1', + 'ios_saf 10.3', + ]; + + return this._supportedBrowsers.some(browser => safariBrowsers.includes(browser)); + } + + /** + * True, when a browser feature is supported partially or fully. + */ + isFeatureSupported(featureId: string): boolean { + // y: feature is fully available + // n: feature is unavailable + // a: feature is partially supported + // x: feature is prefixed + const criteria = [ + 'y', + 'a', + ]; + + const data = feature(features[featureId]); + + return !this._supportedBrowsers + .some(browser => { + const [agentId, version] = browser.split(' '); + + const browserData = data.stats[agentId]; + const featureStatus = (browserData && browserData[version]) as string | undefined; + + // We are only interested in the first character + // Ex: when 'a #4 #5', we only need to check for 'a' + // as for such cases we should polyfill these features as needed + return !featureStatus || !criteria.includes(featureStatus.charAt(0)); + }); + } +} diff --git a/packages/angular_devkit/build_angular/src/utils/build-browser-features_spec.ts b/packages/angular_devkit/build_angular/src/utils/build-browser-features_spec.ts new file mode 100644 index 000000000000..0f111b563e1d --- /dev/null +++ b/packages/angular_devkit/build_angular/src/utils/build-browser-features_spec.ts @@ -0,0 +1,195 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + + +import { TestProjectHost } from '@angular-devkit/architect/testing'; +import { getSystemPath, join } from '@angular-devkit/core'; +import { ScriptTarget } from 'typescript'; +import { BuildBrowserFeatures } from './build-browser-features'; + +const devkitRoot = (global as any)._DevKitRoot; // tslint:disable-line:no-any +const workspaceRoot = join( + devkitRoot, + 'tests/angular_devkit/build_angular/hello-world-app/'); + +const host = new TestProjectHost(workspaceRoot); + +describe('BuildBrowserFeatures', () => { + let workspaceRootSysPath = ''; + beforeEach(async () => { + await host.initialize().toPromise(); + workspaceRootSysPath = getSystemPath(host.root()); + }); + + afterEach(async () => host.restore().toPromise()); + + describe('isDifferentialLoadingNeeded', () => { + it('should be true for for IE 9-11 and ES2015', () => { + host.writeMultipleFiles({ + 'browserslist': 'IE 9-11', + }); + + const buildBrowserFeatures = new BuildBrowserFeatures( + workspaceRootSysPath, + ScriptTarget.ES2015, + ); + expect(buildBrowserFeatures.isDifferentialLoadingNeeded()).toBe(true); + }); + + it('should be false for Chrome and ES2015', () => { + host.writeMultipleFiles({ + 'browserslist': 'last 1 chrome version', + }); + + const buildBrowserFeatures = new BuildBrowserFeatures( + workspaceRootSysPath, + ScriptTarget.ES2015, + ); + expect(buildBrowserFeatures.isDifferentialLoadingNeeded()).toBe(false); + }); + + it('detects no need for differential loading for target is ES5', () => { + host.writeMultipleFiles({ + 'browserslist': 'last 1 chrome version', + }); + + const buildBrowserFeatures = new BuildBrowserFeatures( + workspaceRootSysPath, + ScriptTarget.ES5, + ); + expect(buildBrowserFeatures.isDifferentialLoadingNeeded()).toBe(false); + }); + + it('should be false for Safari 10.1 when target is ES2015', () => { + host.writeMultipleFiles({ + 'browserslist': 'Safari 10.1', + }); + + const buildBrowserFeatures = new BuildBrowserFeatures( + workspaceRootSysPath, + ScriptTarget.ES2015, + ); + expect(buildBrowserFeatures.isDifferentialLoadingNeeded()).toBe(false); + }); + }); + + describe('isFeatureSupported', () => { + it('should be true for es6-module and Safari 10.1', () => { + host.writeMultipleFiles({ + 'browserslist': 'Safari 10.1', + }); + + const buildBrowserFeatures = new BuildBrowserFeatures( + workspaceRootSysPath, + ScriptTarget.ES2015, + ); + expect(buildBrowserFeatures.isFeatureSupported('es6-module')).toBe(true); + }); + + it('should be false for es6-module and IE9', () => { + host.writeMultipleFiles({ + 'browserslist': 'IE 9', + }); + + const buildBrowserFeatures = new BuildBrowserFeatures( + workspaceRootSysPath, + ScriptTarget.ES2015, + ); + expect(buildBrowserFeatures.isFeatureSupported('es6-module')).toBe(false); + }); + + it('should be true for es6-module and last 1 chrome version', () => { + host.writeMultipleFiles({ + 'browserslist': 'last 1 chrome version', + }); + + const buildBrowserFeatures = new BuildBrowserFeatures( + workspaceRootSysPath, + ScriptTarget.ES2015, + ); + expect(buildBrowserFeatures.isFeatureSupported('es6-module')).toBe(true); + }); + + it('should be true for es6-module and Edge 18', () => { + host.writeMultipleFiles({ + 'browserslist': 'Edge 18', + }); + + const buildBrowserFeatures = new BuildBrowserFeatures( + workspaceRootSysPath, + ScriptTarget.ES2015, + ); + expect(buildBrowserFeatures.isFeatureSupported('es6-module')).toBe(true); + }); + }); + + describe('isNoModulePolyfillNeeded', () => { + it('should be false for Safari 10.1 when target is ES5', () => { + host.writeMultipleFiles({ + 'browserslist': 'Safari 10.1', + }); + + const buildBrowserFeatures = new BuildBrowserFeatures( + workspaceRootSysPath, + ScriptTarget.ES5, + ); + expect(buildBrowserFeatures.isNoModulePolyfillNeeded()).toBe(false); + }); + + it('should be false for Safari 10.1 when target is ES2015', () => { + host.writeMultipleFiles({ + 'browserslist': 'Safari 10.1', + }); + + const buildBrowserFeatures = new BuildBrowserFeatures( + workspaceRootSysPath, + ScriptTarget.ES2015, + ); + expect(buildBrowserFeatures.isNoModulePolyfillNeeded()).toBe(false); + }); + + it('should be true for Safari 9+ when target is ES2015', () => { + host.writeMultipleFiles({ + 'browserslist': 'Safari >= 9', + }); + + const buildBrowserFeatures = new BuildBrowserFeatures( + workspaceRootSysPath, + ScriptTarget.ES2015, + ); + expect(buildBrowserFeatures.isNoModulePolyfillNeeded()).toBe(true); + }); + + it('should be false for Safari 9+ when target is ES5', () => { + host.writeMultipleFiles({ + 'browserslist': 'Safari >= 9', + }); + + const buildBrowserFeatures = new BuildBrowserFeatures( + workspaceRootSysPath, + ScriptTarget.ES5, + ); + expect(buildBrowserFeatures.isNoModulePolyfillNeeded()).toBe(false); + }); + + it('should be false when not supporting Safari 10.1 target is ES2015', () => { + host.writeMultipleFiles({ + 'browserslist': ` + Edge 18 + IE 9 + `, + }); + + const buildBrowserFeatures = new BuildBrowserFeatures( + workspaceRootSysPath, + ScriptTarget.ES2015, + ); + expect(buildBrowserFeatures.isNoModulePolyfillNeeded()).toBe(false); + }); + }); +}); diff --git a/packages/angular_devkit/build_angular/src/utils/differential-loading.ts b/packages/angular_devkit/build_angular/src/utils/differential-loading.ts deleted file mode 100644 index 456007ebff5b..000000000000 --- a/packages/angular_devkit/build_angular/src/utils/differential-loading.ts +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @license - * Copyright Google Inc. All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import * as browserslist from 'browserslist'; -import * as caniuse from 'caniuse-api'; -import { ScriptTarget } from 'typescript'; - - -export function isDifferentialLoadingNeeded( - projectRoot: string, - target: ScriptTarget = ScriptTarget.ES5): boolean { - - const supportES2015 = target !== ScriptTarget.ES3 && target !== ScriptTarget.ES5; - - return supportES2015 && isEs5SupportNeeded(projectRoot); -} - -export function isEs5SupportNeeded(projectRoot: string): boolean { - const browsersList: string[] = browserslist( - undefined, { - path: projectRoot, - }); - - return !caniuse.isSupported('es6-module', browsersList.join(', ')); -} diff --git a/packages/angular_devkit/build_angular/src/utils/differential-loading_spec.ts b/packages/angular_devkit/build_angular/src/utils/differential-loading_spec.ts deleted file mode 100644 index 1307fd9f67cd..000000000000 --- a/packages/angular_devkit/build_angular/src/utils/differential-loading_spec.ts +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @license - * Copyright Google Inc. All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - - -import { TestProjectHost } from '@angular-devkit/architect/testing'; -import { getSystemPath, join } from '@angular-devkit/core'; -import { ScriptTarget } from 'typescript'; -import { isDifferentialLoadingNeeded } from './differential-loading'; - -const devkitRoot = (global as any)._DevKitRoot; // tslint:disable-line:no-any -const workspaceRoot = join( - devkitRoot, - 'tests/angular_devkit/build_angular/hello-world-app/'); - -const host = new TestProjectHost(workspaceRoot); - - -describe('differential loading', () => { - - beforeEach(async () => host.initialize().toPromise()); - afterEach(async () => host.restore().toPromise()); - - it('detects the need for differential loading for IE 9-11 and ES2015', () => { - host.writeMultipleFiles({ - 'browserslist': 'IE 9-11', - }); - - const needed = isDifferentialLoadingNeeded(getSystemPath(host.root()), ScriptTarget.ES2015); - expect(needed).toBe(true); - }); - - it('detects no need for differential loading for Chrome and ES2015', () => { - host.writeMultipleFiles({ - 'browserslist': 'last 1 chrome version', - }); - - const needed = isDifferentialLoadingNeeded(getSystemPath(host.root()), ScriptTarget.ES2015); - - expect(needed).toBe(false); - }); - - it('detects no need for differential loading for target is ES5', () => { - host.writeMultipleFiles({ - 'browserslist': 'last 1 chrome version', - }); - - const needed = isDifferentialLoadingNeeded(getSystemPath(host.root()), ScriptTarget.ES5); - - expect(needed).toBe(false); - }); -}); diff --git a/packages/angular_devkit/build_angular/src/utils/index.ts b/packages/angular_devkit/build_angular/src/utils/index.ts index 0f297fff122b..8cd7670f0a9b 100644 --- a/packages/angular_devkit/build_angular/src/utils/index.ts +++ b/packages/angular_devkit/build_angular/src/utils/index.ts @@ -5,9 +5,10 @@ * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ + +export * from './build-browser-features'; export * from './default-progress'; export * from './delete-output-dir'; -export * from './differential-loading'; export * from './run-module-as-observable-fork'; export * from './normalize-file-replacements'; export * from './normalize-asset-patterns'; diff --git a/packages/angular_devkit/build_angular/src/utils/webpack-browser-config.ts b/packages/angular_devkit/build_angular/src/utils/webpack-browser-config.ts index 94966ee738bd..df478dbfde32 100644 --- a/packages/angular_devkit/build_angular/src/utils/webpack-browser-config.ts +++ b/packages/angular_devkit/build_angular/src/utils/webpack-browser-config.ts @@ -24,7 +24,7 @@ import { getEsVersionForFileName } from '../angular-cli-files/models/webpack-con import { readTsconfig } from '../angular-cli-files/utilities/read-tsconfig'; import { Schema as BrowserBuilderSchema } from '../browser/schema'; import { NormalizedBrowserBuilderSchema, defaultProgress, normalizeBrowserSchema } from '../utils'; -import { isDifferentialLoadingNeeded } from './differential-loading'; +import { BuildBrowserFeatures } from './build-browser-features'; const SpeedMeasurePlugin = require('speed-measure-webpack-plugin'); const webpackMerge = require('webpack-merge'); @@ -53,9 +53,11 @@ export async function generateWebpackConfig( // At the moment, only the browser builder supports differential loading // However this config generation is used by multiple builders such as dev-server - const scriptTarget = tsConfig.options.target; + const scriptTarget = tsConfig.options.target || ts.ScriptTarget.ES5; + const buildBrowserFeatures = new BuildBrowserFeatures(projectRoot, scriptTarget); const differentialLoading = context.builder.builderName === 'browser' - && isDifferentialLoadingNeeded(projectRoot, scriptTarget) && !options.watch; + && !options.watch + && buildBrowserFeatures.isDifferentialLoadingNeeded(); const scriptTargets = [scriptTarget]; diff --git a/packages/angular_devkit/build_angular/test/browser/differential_loading_spec_large.ts b/packages/angular_devkit/build_angular/test/browser/differential_loading_spec_large.ts index 62c80dafa543..16530d00e934 100644 --- a/packages/angular_devkit/build_angular/test/browser/differential_loading_spec_large.ts +++ b/packages/angular_devkit/build_angular/test/browser/differential_loading_spec_large.ts @@ -73,8 +73,6 @@ describe('Browser Builder with differential loading', () => { 'main.js', 'main.js.map', - 'polyfills-es5.js', - 'polyfills-es5.js.map', 'polyfills.js', 'polyfills.js.map', diff --git a/tests/angular_devkit/build_angular/hello-world-app/package.json b/tests/angular_devkit/build_angular/hello-world-app/package.json index 97164be01a98..5aecb7dd20b6 100644 --- a/tests/angular_devkit/build_angular/hello-world-app/package.json +++ b/tests/angular_devkit/build_angular/hello-world-app/package.json @@ -23,7 +23,6 @@ "@angular/platform-browser": "^6.0.0-rc.0", "@angular/platform-browser-dynamic": "^6.0.0-rc.0", "@angular/router": "^6.0.0-rc.0", - "core-js": "^2.4.1", "rxjs": "~6.2.0", "zone.js": "^0.8.19" }, diff --git a/tests/angular_devkit/build_angular/hello-world-app/src/polyfills.ts b/tests/angular_devkit/build_angular/hello-world-app/src/polyfills.ts index d7fd9a7ba789..bd13d5722895 100644 --- a/tests/angular_devkit/build_angular/hello-world-app/src/polyfills.ts +++ b/tests/angular_devkit/build_angular/hello-world-app/src/polyfills.ts @@ -25,41 +25,39 @@ * BROWSER POLYFILLS */ -/** IE9, IE10 and IE11 requires all of the following polyfills. **/ -// import 'core-js/es6/symbol'; -// import 'core-js/es6/object'; -// import 'core-js/es6/function'; -// import 'core-js/es6/parse-int'; -// import 'core-js/es6/parse-float'; -// import 'core-js/es6/number'; -// import 'core-js/es6/math'; -// import 'core-js/es6/string'; -// import 'core-js/es6/date'; -// import 'core-js/es6/array'; -// import 'core-js/es6/regexp'; -// import 'core-js/es6/map'; -// import 'core-js/es6/weak-map'; -// import 'core-js/es6/set'; - /** IE10 and IE11 requires the following for NgClass support on SVG elements */ // import 'classlist.js'; // Run `npm install --save classlist.js`. -/** IE10 and IE11 requires the following for the Reflect API. */ -// import 'core-js/es6/reflect'; - - -/** Evergreen browsers require these. **/ -// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove. -import 'core-js/es7/reflect'; - - /** - * Required to support Web Animations `@angular/platform-browser/animations`. - * Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation - **/ + * Web Animations `@angular/platform-browser/animations` + * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. + * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). + */ // import 'web-animations-js'; // Run `npm install --save web-animations-js`. - +/** + * By default, zone.js will patch all possible macroTask and DomEvents + * user can disable parts of macroTask/DomEvents patch by setting following flags + * because those flags need to be set before `zone.js` being loaded, and webpack + * will put import in the top of bundle, so user need to create a separate file + * in this directory (for example: zone-flags.ts), and put the following flags + * into that file, and then add the following code before importing zone.js. + * import './zone-flags.ts'; + * + * The flags allowed in zone-flags.ts are listed here. + * + * The following flags will work for all browsers. + * + * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame + * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick + * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames + * + * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js + * with the following flag, it will bypass `zone.js` patch for IE/Edge + * + * (window as any).__Zone_enable_cross_context_check = true; + * + */ /*************************************************************************************************** * Zone JS is required by default for Angular itself. @@ -67,7 +65,6 @@ import 'core-js/es7/reflect'; import 'zone.js/dist/zone'; // Included with Angular CLI. - /*************************************************************************************************** * APPLICATION IMPORTS */ diff --git a/tests/legacy-cli/e2e/tests/misc/support-safari-10.1.ts b/tests/legacy-cli/e2e/tests/misc/support-safari-10.1.ts new file mode 100644 index 000000000000..f78cb217bdcb --- /dev/null +++ b/tests/legacy-cli/e2e/tests/misc/support-safari-10.1.ts @@ -0,0 +1,42 @@ +import { oneLineTrim } from 'common-tags'; +import { + expectFileNotToExist, + expectFileToExist, + expectFileToMatch, + writeFile, +} from '../../utils/fs'; +import { ng } from '../../utils/process'; + +export default async function () { + await writeFile('browserslist', 'Safari 10.1'); + await ng('build'); + await expectFileNotToExist('dist/test-project/polyfills-es5.js'); + await expectFileNotToExist('dist/test-project/polyfills-nomodule-es5.js'); + await expectFileToMatch('dist/test-project/index.html', oneLineTrim` + + + + + + `); + + await writeFile('browserslist', ` + IE 9 + Safari 10.1 + `); + await ng('build'); + await expectFileToExist('dist/test-project/polyfills-nomodule-es5.js'); + await expectFileToMatch('dist/test-project/index.html', oneLineTrim` + + + + + + + + + + + + `); +} diff --git a/yarn.lock b/yarn.lock index 72b867017af8..c98c5eef4ef0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -300,10 +300,10 @@ resolved "https://registry.yarnpkg.com/@types/browserslist/-/browserslist-4.4.0.tgz#e2a5f7f8c7e97afb39f50812a77e5230d3ca2353" integrity sha512-hrIjWSu7Hh96/rKlpChe58qHEwIZ0+F5Zf4QNdvSVP5LUXbaJM04g9tBjo702VTNqPZr5znEJeqNR3nAV3vJPg== -"@types/caniuse-api@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/caniuse-api/-/caniuse-api-3.0.0.tgz#af31cc52062be0ab24583be072fd49b634dcc2fe" - integrity sha512-wT1VfnScjAftZsvLYaefu/UuwYJdYBwD2JDL2OQd01plGmuAoir5V6HnVHgrfh7zEwcasoiyO2wQ+W58sNh2sw== +"@types/caniuse-lite@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/caniuse-lite/-/caniuse-lite-1.0.0.tgz#6506ed4b3f8d19def130d19419062960e86cc3bc" + integrity sha512-g28510gzJpFL0xqvuGAlI+dfIr3qvUcZQVFc7f7u2VlWVqI1oBkWhGLYh3fXfoflR7HRnU4w0NRux0pPJQ7VVg== "@types/caseless@*": version "0.12.1" @@ -1871,20 +1871,10 @@ camelcase@^5.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -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: - version "1.0.30000955" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000955.tgz#360fdb9a1e41d6dd996130411334e44a39e4446d" - integrity sha512-6AwmIKgqCYfDWWadRkAuZSHMQP4Mmy96xAXEdRBlN/luQhlRYOKgwOlZ9plpCOsVbBuqbTmGqDK3JUM/nlr8CA== +caniuse-lite@1.0.30000974: + version "1.0.30000974" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000974.tgz#b7afe14ee004e97ce6dc73e3f878290a12928ad8" + integrity sha512-xc3rkNS/Zc3CmpMKuczWEdY2sZgx09BkAxfvkxlAEBTqcMHeL8QnPqhKse+5sRTi3nrw2pJwToD2WvKn1Uhvww== caniuse-lite@^1.0.30000898: version "1.0.30000903" @@ -5870,11 +5860,6 @@ lodash.get@^4.4.2: resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= -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.tail@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664" @@ -5895,11 +5880,6 @@ lodash.templatesettings@^4.0.0: dependencies: lodash._reinterpolate "~3.0.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= - lodash@^4.16.6, lodash@^4.17.11, lodash@^4.17.5: version "4.17.11" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"