After upgrading to Angular 8, ng build generates a proper index.html that supports differential loading however ng serve generates a different index.html that contains references to only some of the generated 'es5' scripts. As a result, the app does not work in ES5 browsers like IE 11.
So far I have:
- confirmed the app runs as expected in modern ES2015+ browsers like Chrome
- confirmed the app worked on IE 11 prior to the Angular 8 upgrade
- compared index.html source in IE 11 to source generated in dist directory from
ng build, can see differences in script references (see sample code below) - searched angular and angular-cli issues on Github and stackoverflow for similar problems
- tried building and serving with and without the soon to be deprecated es5BrowserSupport option in angular.json
- updated to the latest versions of @angular-devkit and @angular packages
The repository I am working on contains an application project and a library project. Here are the relevant architect targets from angular.json after the Angular 8 upgrade:
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/ng-shared-components-tester",
"index": "projects/ng-shared-components-tester/src/index.html",
"main": "projects/ng-shared-components-tester/src/main.ts",
"polyfills": "projects/ng-shared-components-tester/src/polyfills.ts",
"tsConfig": "projects/ng-shared-components-tester/tsconfig.app.json",
"assets": [
"projects/ng-shared-components-tester/src/favicon.ico",
"projects/ng-shared-components-tester/src/assets"
],
"styles": [
"node_modules/bootstrap/dist/css/bootstrap.min.css",
"projects/ng-shared-components-tester/src/styles.css",
"node_modules/abc-emerald-standards/dist/emerald/assets/css/default.css",
"node_modules/abc-emerald-standards/dist/emerald/assets/css/forms.css"
],
"scripts": [],
"es5BrowserSupport": true
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "projects/ng-shared-components-tester/src/environments/environment.ts",
"with": "projects/ng-shared-components-tester/src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "ng-shared-components-tester:build"
},
"configurations": {
"production": {
"browserTarget": "ng-shared-components-tester:build:production"
}
}
},
Here is the browserlist file with IE 11 support enabled:
> 0.5%
last 4 versions
IE 11
not dead
tsconfig.json:
{
"compileOnSave": false,
"compilerOptions": {
"importHelpers": true,
"outDir": "./dist/out-tsc",
"baseUrl": "./",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es2015",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2018",
"dom"
],
"module": "esnext",
"paths": {
"@abc/ng-shared-components": [
"dist/abc/ng-shared-components"
],
"@abc/ng-shared-components/*": [
"dist/abc/ng-shared-components/*"
]
}
},
"angularCompilerOptions": {
"annotateForClosureCompiler": true,
"skipTemplateCodegen": true,
"strictMetadataEmit": true,
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true
},
}
Expected Result
ng build is generated the expected result in dist/ng-shared-components-tester/index.html:
<body>
<app-root></app-root>
<script src="runtime-es2015.js" type="module"></script>
<script src="polyfills-es2015.js" type="module"></script>
<script src="runtime-es5.js" nomodule></script>
<script src="polyfills-es5.js" nomodule></script>
<script src="styles-es2015.js" type="module"></script>
<script src="styles-es5.js" nomodule></script>
<script src="vendor-es2015.js" type="module"></script>
<script src="main-es2015.js" type="module"></script>
<script src="vendor-es5.js" nomodule></script>
<script src="main-es5.js" nomodule></script>
</body>
Actual Result
ng serve is serving up an index.html to IE 11 that only contains the ES5 version of pollfills.js:
<body>
<app-root></app-root>
<script src="runtime.js"></script>
<script src="polyfills-es5.js" nomodule></script>
<script src="polyfills.js"></script><script src="styles.js"></script>
<script src="vendor.js"></script>
<script src="main.js"></script>
</body>
After a little more digging I found this discussion on GitHub that indicates differential loading is disabled by default for ng serve and ng build --watch by design. This appears to be done for performance reasons (differential loading requires 2 builds to run, ES5 and non-ES5). There is a workaround to use ES5 bundles instead of the default bundles.
That is the correct behavior of your code .Angular CLi will detect the browser and inject the polyfill script at the runtime like this
So if you are using older browser version you will the script that have nomodule tag
You can read it more here
来源:https://stackoverflow.com/questions/56529710/differential-loading-script-references-in-index-html-different-when-running-ng-s
