Skip to content

Commit 08bb738

Browse files
authored
fix(polyfills): move polyfills to own entry point (#3812)
Polyfills found in polyfills.ts would not be available for scripts due to being loaded in the main bundle only. This PR loads polyfills as a separate entry point, before everything else. Extra documentation also added to polyfills.ts. Fix #2752 Fix #3309 Fix #4140
1 parent 72f0d72 commit 08bb738

File tree

14 files changed

+100
-22
lines changed

14 files changed

+100
-22
lines changed

Diff for: packages/angular-cli/blueprints/ng2/files/__path__/main.ts

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import './polyfills.ts';
2-
31
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
42
import { enableProdMode } from '@angular/core';
53
import { environment } from './environments/environment';

Diff for: packages/angular-cli/blueprints/ng2/files/__path__/polyfills.ts

+21-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// This file includes polyfills needed by Angular and is loaded before
2-
// the app. You can add your own extra polyfills to this file.
1+
// This file includes polyfills needed by Angular and is loaded before the app.
2+
// You can add your own extra polyfills to this file.
33
import 'core-js/es6/symbol';
44
import 'core-js/es6/object';
55
import 'core-js/es6/function';
@@ -17,3 +17,22 @@ import 'core-js/es6/reflect';
1717

1818
import 'core-js/es7/reflect';
1919
import 'zone.js/dist/zone';
20+
21+
// If you need to support the browsers/features below, uncomment the import
22+
// and run `npm install import-name-here';
23+
// Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
24+
25+
// Needed for: IE9
26+
// import 'classlist.js';
27+
28+
// Animations
29+
// Needed for: All but Chrome and Firefox, Not supported in IE9
30+
// import 'web-animations-js';
31+
32+
// Date, currency, decimal and percent pipes
33+
// Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10
34+
// import 'intl';
35+
36+
// NgClass on SVG elements
37+
// Needed for: IE10, IE11
38+
// import 'classlist.js';

Diff for: packages/angular-cli/blueprints/ng2/files/__path__/test.ts

-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
22

3-
import './polyfills.ts';
4-
53
import 'zone.js/dist/long-stack-trace-zone';
64
import 'zone.js/dist/proxy.js';
75
import 'zone.js/dist/sync-test';

Diff for: packages/angular-cli/blueprints/ng2/files/angular-cli.json

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
],
1414
"index": "index.html",
1515
"main": "main.ts",
16+
"polyfills": "polyfills.ts",
1617
"test": "test.ts",
1718
"tsconfig": "tsconfig.json",
1819
"prefix": "<%= prefix %>",

Diff for: packages/angular-cli/lib/config/schema.json

+3
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@
5555
"main": {
5656
"type": "string"
5757
},
58+
"polyfills": {
59+
"type": "string"
60+
},
5861
"test": {
5962
"type": "string"
6063
},

Diff for: packages/angular-cli/models/webpack-build-common.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ export function getWebpackCommonConfig(
5252
entryPoints['main'] = [path.resolve(appRoot, appConfig.main)];
5353
}
5454

55+
if (appConfig.polyfills) {
56+
entryPoints['polyfills'] = [path.resolve(appRoot, appConfig.polyfills)];
57+
}
58+
5559
// determine hashing format
5660
const hashFormat = getOutputHashFormat(outputHashing);
5761

@@ -138,7 +142,7 @@ export function getWebpackCommonConfig(
138142
new HtmlWebpackPlugin({
139143
template: path.resolve(appRoot, appConfig.index),
140144
filename: path.resolve(appConfig.outDir, appConfig.index),
141-
chunksSortMode: packageChunkSort(['inline', 'styles', 'scripts', 'vendor', 'main']),
145+
chunksSortMode: packageChunkSort(appConfig),
142146
excludeChunks: lazyChunks,
143147
xhtml: true
144148
}),

Diff for: packages/angular-cli/models/webpack-config.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export class NgCliWebpackConfig {
5656

5757
let config = webpackMerge(baseConfig, targetConfigPartial);
5858

59-
if (appConfig.main) {
59+
if (appConfig.main || appConfig.polyfills) {
6060
const typescriptConfigPartial = isAoT
6161
? getWebpackAotConfigPartial(projectRoot, appConfig, i18nFile, i18nFormat, locale)
6262
: getWebpackNonAotConfigPartial(projectRoot, appConfig);

Diff for: packages/angular-cli/plugins/karma.js

+13
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,19 @@ const init = (config) => {
6868
.map((file) => config.preprocessors[file])
6969
.map((arr) => arr.splice(arr.indexOf('angular-cli'), 1, 'webpack', 'sourcemap'));
7070

71+
// Add polyfills file
72+
if (appConfig.polyfills) {
73+
const polyfillsFile = path.resolve(appRoot, appConfig.polyfills);
74+
const polyfillsPattern = {
75+
pattern: polyfillsFile,
76+
included: true,
77+
served: true,
78+
watched: true
79+
}
80+
Array.prototype.unshift.apply(config.files, [polyfillsPattern]);
81+
config.preprocessors[polyfillsFile] = ['webpack', 'sourcemap'];
82+
}
83+
7184
// Add global scripts
7285
if (appConfig.scripts && appConfig.scripts.length > 0) {
7386
const globalScriptPatterns = appConfig.scripts

Diff for: packages/angular-cli/utilities/package-chunk-sort.ts

+28-9
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,36 @@
1-
export function packageChunkSort(packages: string[]) {
2-
return function sort(left: any, right: any) {
3-
let leftIndex = packages.indexOf(left.names[0]);
4-
let rightindex = packages.indexOf(right.names[0]);
1+
import { ExtraEntry, extraEntryParser } from '../models/webpack-build-utils';
52

6-
if ( leftIndex < 0 || rightindex < 0) {
7-
// Unknown packages are loaded last
8-
return 1;
3+
// Sort chunks according to a predefined order:
4+
// inline, polyfills, all scripts, all styles, vendor, main
5+
export function packageChunkSort(appConfig: any) {
6+
let entryPoints = ['inline', 'polyfills'];
7+
8+
const pushExtraEntries = (extraEntry: ExtraEntry) => {
9+
if (entryPoints.indexOf(extraEntry.entry) === -1) {
10+
entryPoints.push(extraEntry.entry);
911
}
12+
};
13+
14+
if (appConfig.scripts) {
15+
extraEntryParser(appConfig.scripts, './', 'scripts').forEach(pushExtraEntries);
16+
}
17+
18+
if (appConfig.styles) {
19+
extraEntryParser(appConfig.styles, './', 'styles').forEach(pushExtraEntries);
20+
}
21+
22+
entryPoints.push(...['vendor', 'main']);
23+
24+
return function sort(left: any, right: any) {
25+
let leftIndex = entryPoints.indexOf(left.names[0]);
26+
let rightindex = entryPoints.indexOf(right.names[0]);
1027

1128
if (leftIndex > rightindex) {
1229
return 1;
30+
} else if (leftIndex < rightindex) {
31+
return -1;
32+
} else {
33+
return 0;
1334
}
14-
15-
return -1;
1635
};
1736
}

Diff for: tests/e2e/tests/build/polyfills.ts

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { expectFileToMatch } from '../../utils/fs';
2+
import { ng } from '../../utils/process';
3+
import { oneLineTrim } from 'common-tags';
4+
5+
export default function () {
6+
return Promise.resolve()
7+
.then(() => ng('build'))
8+
// files were created successfully
9+
.then(() => expectFileToMatch('dist/polyfills.bundle.js', 'core-js'))
10+
.then(() => expectFileToMatch('dist/polyfills.bundle.js', 'zone.js'))
11+
// index.html lists the right bundles
12+
.then(() => expectFileToMatch('dist/index.html', oneLineTrim`
13+
<script type="text/javascript" src="inline.bundle.js"></script>
14+
<script type="text/javascript" src="polyfills.bundle.js"></script>
15+
`));
16+
}

Diff for: tests/e2e/tests/build/scripts-array.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,10 @@ export default function () {
4545
`))
4646
.then(() => expectFileToMatch('dist/index.html', oneLineTrim`
4747
<script type="text/javascript" src="inline.bundle.js"></script>
48+
<script type="text/javascript" src="polyfills.bundle.js"></script>
49+
<script type="text/javascript" src="scripts.bundle.js"></script>
4850
<script type="text/javascript" src="renamed-script.bundle.js"></script>
4951
<script type="text/javascript" src="common-entry.bundle.js"></script>
50-
<script type="text/javascript" src="scripts.bundle.js"></script>
5152
<script type="text/javascript" src="vendor.bundle.js"></script>
5253
<script type="text/javascript" src="main.bundle.js"></script>
5354
`))

Diff for: tests/e2e/tests/build/styles/styles-array.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,15 @@ export default function () {
4646
.then(() => expectToFail(() => expectFileToExist('dist/renamed-lazy-style.bundle.js')))
4747
// index.html lists the right bundles
4848
.then(() => expectFileToMatch('dist/index.html', oneLineTrim`
49-
<link href="renamed-style.bundle.css" rel="stylesheet"/>
50-
<link href="styles.bundle.css" rel="stylesheet"/>
5149
<link href="common-entry.bundle.css" rel="stylesheet"/>
50+
<link href="styles.bundle.css" rel="stylesheet"/>
51+
<link href="renamed-style.bundle.css" rel="stylesheet"/>
5252
`))
5353
.then(() => expectFileToMatch('dist/index.html', oneLineTrim`
5454
<script type="text/javascript" src="inline.bundle.js"></script>
55-
<script type="text/javascript" src="vendor.bundle.js"></script>
55+
<script type="text/javascript" src="polyfills.bundle.js"></script>
5656
<script type="text/javascript" src="common-entry.bundle.js"></script>
57+
<script type="text/javascript" src="vendor.bundle.js"></script>
5758
<script type="text/javascript" src="main.bundle.js"></script>
5859
`))
5960
.then(() => ng('build', '--no-extract-css'))

Diff for: tests/e2e/tests/misc/minimal-config.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ export default function () {
77
.then(() => writeFile('angular-cli.json', JSON.stringify({
88
apps: [{
99
root: 'src',
10-
main: 'main.ts'
10+
main: 'main.ts',
11+
scripts: [
12+
'../node_modules/core-js/client/shim.min.js',
13+
'../node_modules/zone.js/dist/zone.js'
14+
]
1115
}],
1216
e2e: { protractor: { config: './protractor.conf.js' } }
1317
})))

Diff for: tests/e2e/tests/third-party/bootstrap.ts

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export default function() {
2323
.then(() => expectFileToMatch('dist/styles.bundle.css', '* Bootstrap'))
2424
.then(() => expectFileToMatch('dist/index.html', oneLineTrim`
2525
<script type="text/javascript" src="inline.bundle.js"></script>
26+
<script type="text/javascript" src="polyfills.bundle.js"></script>
2627
<script type="text/javascript" src="scripts.bundle.js"></script>
2728
<script type="text/javascript" src="vendor.bundle.js"></script>
2829
<script type="text/javascript" src="main.bundle.js"></script>

0 commit comments

Comments
 (0)