diff --git a/packages/angular-cli/blueprints/ng2/files/__path__/main.ts b/packages/angular-cli/blueprints/ng2/files/__path__/main.ts
index ac78a713c2d1..46c1c73e209e 100644
--- a/packages/angular-cli/blueprints/ng2/files/__path__/main.ts
+++ b/packages/angular-cli/blueprints/ng2/files/__path__/main.ts
@@ -1,5 +1,3 @@
-import './polyfills.ts';
-
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { environment } from './environments/environment';
diff --git a/packages/angular-cli/blueprints/ng2/files/__path__/polyfills.ts b/packages/angular-cli/blueprints/ng2/files/__path__/polyfills.ts
index 4749399c2da0..1bdd4d3c6ef2 100644
--- a/packages/angular-cli/blueprints/ng2/files/__path__/polyfills.ts
+++ b/packages/angular-cli/blueprints/ng2/files/__path__/polyfills.ts
@@ -1,5 +1,5 @@
-// This file includes polyfills needed by Angular and is loaded before
-// the app. You can add your own extra polyfills to this file.
+// This file includes polyfills needed by Angular and is loaded before the app.
+// You can add your own extra polyfills to this file.
import 'core-js/es6/symbol';
import 'core-js/es6/object';
import 'core-js/es6/function';
@@ -17,3 +17,22 @@ import 'core-js/es6/reflect';
import 'core-js/es7/reflect';
import 'zone.js/dist/zone';
+
+// If you need to support the browsers/features below, uncomment the import
+// and run `npm install import-name-here';
+// Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
+
+// Needed for: IE9
+// import 'classlist.js';
+
+// Animations
+// Needed for: All but Chrome and Firefox, Not supported in IE9
+// import 'web-animations-js';
+
+// Date, currency, decimal and percent pipes
+// Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10
+// import 'intl';
+
+// NgClass on SVG elements
+// Needed for: IE10, IE11
+// import 'classlist.js';
diff --git a/packages/angular-cli/blueprints/ng2/files/__path__/test.ts b/packages/angular-cli/blueprints/ng2/files/__path__/test.ts
index 430d4df98fa0..9bf72267e9b1 100644
--- a/packages/angular-cli/blueprints/ng2/files/__path__/test.ts
+++ b/packages/angular-cli/blueprints/ng2/files/__path__/test.ts
@@ -1,7 +1,5 @@
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
-import './polyfills.ts';
-
import 'zone.js/dist/long-stack-trace-zone';
import 'zone.js/dist/proxy.js';
import 'zone.js/dist/sync-test';
diff --git a/packages/angular-cli/blueprints/ng2/files/angular-cli.json b/packages/angular-cli/blueprints/ng2/files/angular-cli.json
index 3e7ec03e8d9d..ea13f8072b9f 100644
--- a/packages/angular-cli/blueprints/ng2/files/angular-cli.json
+++ b/packages/angular-cli/blueprints/ng2/files/angular-cli.json
@@ -13,6 +13,7 @@
],
"index": "index.html",
"main": "main.ts",
+ "polyfills": "polyfills.ts",
"test": "test.ts",
"tsconfig": "tsconfig.json",
"prefix": "<%= prefix %>",
diff --git a/packages/angular-cli/lib/config/schema.json b/packages/angular-cli/lib/config/schema.json
index 64c07bbd2b9a..67b0473f88e5 100644
--- a/packages/angular-cli/lib/config/schema.json
+++ b/packages/angular-cli/lib/config/schema.json
@@ -55,6 +55,9 @@
"main": {
"type": "string"
},
+ "polyfills": {
+ "type": "string"
+ },
"test": {
"type": "string"
},
diff --git a/packages/angular-cli/models/webpack-build-common.ts b/packages/angular-cli/models/webpack-build-common.ts
index ae2d05e698cd..3efc9dc2aabd 100644
--- a/packages/angular-cli/models/webpack-build-common.ts
+++ b/packages/angular-cli/models/webpack-build-common.ts
@@ -52,6 +52,10 @@ export function getWebpackCommonConfig(
entryPoints['main'] = [path.resolve(appRoot, appConfig.main)];
}
+ if (appConfig.polyfills) {
+ entryPoints['polyfills'] = [path.resolve(appRoot, appConfig.polyfills)];
+ }
+
// determine hashing format
const hashFormat = getOutputHashFormat(outputHashing);
@@ -138,7 +142,7 @@ export function getWebpackCommonConfig(
new HtmlWebpackPlugin({
template: path.resolve(appRoot, appConfig.index),
filename: path.resolve(appConfig.outDir, appConfig.index),
- chunksSortMode: packageChunkSort(['inline', 'styles', 'scripts', 'vendor', 'main']),
+ chunksSortMode: packageChunkSort(appConfig),
excludeChunks: lazyChunks,
xhtml: true
}),
diff --git a/packages/angular-cli/models/webpack-config.ts b/packages/angular-cli/models/webpack-config.ts
index 07134219e180..f46231955904 100644
--- a/packages/angular-cli/models/webpack-config.ts
+++ b/packages/angular-cli/models/webpack-config.ts
@@ -56,7 +56,7 @@ export class NgCliWebpackConfig {
let config = webpackMerge(baseConfig, targetConfigPartial);
- if (appConfig.main) {
+ if (appConfig.main || appConfig.polyfills) {
const typescriptConfigPartial = isAoT
? getWebpackAotConfigPartial(projectRoot, appConfig, i18nFile, i18nFormat, locale)
: getWebpackNonAotConfigPartial(projectRoot, appConfig);
diff --git a/packages/angular-cli/plugins/karma.js b/packages/angular-cli/plugins/karma.js
index 16c4fc7cafea..a53c2e732181 100644
--- a/packages/angular-cli/plugins/karma.js
+++ b/packages/angular-cli/plugins/karma.js
@@ -68,6 +68,19 @@ const init = (config) => {
.map((file) => config.preprocessors[file])
.map((arr) => arr.splice(arr.indexOf('angular-cli'), 1, 'webpack', 'sourcemap'));
+ // Add polyfills file
+ if (appConfig.polyfills) {
+ const polyfillsFile = path.resolve(appRoot, appConfig.polyfills);
+ const polyfillsPattern = {
+ pattern: polyfillsFile,
+ included: true,
+ served: true,
+ watched: true
+ }
+ Array.prototype.unshift.apply(config.files, [polyfillsPattern]);
+ config.preprocessors[polyfillsFile] = ['webpack', 'sourcemap'];
+ }
+
// Add global scripts
if (appConfig.scripts && appConfig.scripts.length > 0) {
const globalScriptPatterns = appConfig.scripts
diff --git a/packages/angular-cli/utilities/package-chunk-sort.ts b/packages/angular-cli/utilities/package-chunk-sort.ts
index 7c4daeb6dbfa..14c044e87547 100644
--- a/packages/angular-cli/utilities/package-chunk-sort.ts
+++ b/packages/angular-cli/utilities/package-chunk-sort.ts
@@ -1,17 +1,36 @@
-export function packageChunkSort(packages: string[]) {
- return function sort(left: any, right: any) {
- let leftIndex = packages.indexOf(left.names[0]);
- let rightindex = packages.indexOf(right.names[0]);
+import { ExtraEntry, extraEntryParser } from '../models/webpack-build-utils';
- if ( leftIndex < 0 || rightindex < 0) {
- // Unknown packages are loaded last
- return 1;
+// Sort chunks according to a predefined order:
+// inline, polyfills, all scripts, all styles, vendor, main
+export function packageChunkSort(appConfig: any) {
+ let entryPoints = ['inline', 'polyfills'];
+
+ const pushExtraEntries = (extraEntry: ExtraEntry) => {
+ if (entryPoints.indexOf(extraEntry.entry) === -1) {
+ entryPoints.push(extraEntry.entry);
}
+ };
+
+ if (appConfig.scripts) {
+ extraEntryParser(appConfig.scripts, './', 'scripts').forEach(pushExtraEntries);
+ }
+
+ if (appConfig.styles) {
+ extraEntryParser(appConfig.styles, './', 'styles').forEach(pushExtraEntries);
+ }
+
+ entryPoints.push(...['vendor', 'main']);
+
+ return function sort(left: any, right: any) {
+ let leftIndex = entryPoints.indexOf(left.names[0]);
+ let rightindex = entryPoints.indexOf(right.names[0]);
if (leftIndex > rightindex) {
return 1;
+ } else if (leftIndex < rightindex) {
+ return -1;
+ } else {
+ return 0;
}
-
- return -1;
};
}
diff --git a/tests/e2e/tests/build/polyfills.ts b/tests/e2e/tests/build/polyfills.ts
new file mode 100644
index 000000000000..2fae001ff3e0
--- /dev/null
+++ b/tests/e2e/tests/build/polyfills.ts
@@ -0,0 +1,16 @@
+import { expectFileToMatch } from '../../utils/fs';
+import { ng } from '../../utils/process';
+import { oneLineTrim } from 'common-tags';
+
+export default function () {
+ return Promise.resolve()
+ .then(() => ng('build'))
+ // files were created successfully
+ .then(() => expectFileToMatch('dist/polyfills.bundle.js', 'core-js'))
+ .then(() => expectFileToMatch('dist/polyfills.bundle.js', 'zone.js'))
+ // index.html lists the right bundles
+ .then(() => expectFileToMatch('dist/index.html', oneLineTrim`
+
+
+ `));
+}
diff --git a/tests/e2e/tests/build/scripts-array.ts b/tests/e2e/tests/build/scripts-array.ts
index f3d2a02ac34e..57cabfa08a2d 100644
--- a/tests/e2e/tests/build/scripts-array.ts
+++ b/tests/e2e/tests/build/scripts-array.ts
@@ -45,9 +45,10 @@ export default function () {
`))
.then(() => expectFileToMatch('dist/index.html', oneLineTrim`
+
+
-
`))
diff --git a/tests/e2e/tests/build/styles/styles-array.ts b/tests/e2e/tests/build/styles/styles-array.ts
index e43c03160914..7e568ff59ec0 100644
--- a/tests/e2e/tests/build/styles/styles-array.ts
+++ b/tests/e2e/tests/build/styles/styles-array.ts
@@ -46,14 +46,15 @@ export default function () {
.then(() => expectToFail(() => expectFileToExist('dist/renamed-lazy-style.bundle.js')))
// index.html lists the right bundles
.then(() => expectFileToMatch('dist/index.html', oneLineTrim`
-
-
+
+
`))
.then(() => expectFileToMatch('dist/index.html', oneLineTrim`
-
+
+
`))
.then(() => ng('build', '--no-extract-css'))
diff --git a/tests/e2e/tests/misc/minimal-config.ts b/tests/e2e/tests/misc/minimal-config.ts
index b04fbf2cecf9..d8ededab39d6 100644
--- a/tests/e2e/tests/misc/minimal-config.ts
+++ b/tests/e2e/tests/misc/minimal-config.ts
@@ -7,7 +7,11 @@ export default function () {
.then(() => writeFile('angular-cli.json', JSON.stringify({
apps: [{
root: 'src',
- main: 'main.ts'
+ main: 'main.ts',
+ scripts: [
+ '../node_modules/core-js/client/shim.min.js',
+ '../node_modules/zone.js/dist/zone.js'
+ ]
}],
e2e: { protractor: { config: './protractor.conf.js' } }
})))
diff --git a/tests/e2e/tests/third-party/bootstrap.ts b/tests/e2e/tests/third-party/bootstrap.ts
index 23f922440970..f99fc436b339 100644
--- a/tests/e2e/tests/third-party/bootstrap.ts
+++ b/tests/e2e/tests/third-party/bootstrap.ts
@@ -23,6 +23,7 @@ export default function() {
.then(() => expectFileToMatch('dist/styles.bundle.css', '* Bootstrap'))
.then(() => expectFileToMatch('dist/index.html', oneLineTrim`
+