網站搜尋

javascript - 在 index.html 中的差異加載腳本引用,在使用 ng serve 與 ng build 運行時不同


升級到 Angular 8 後,ng build 會生成一個支援差異加載的正確 index.html,但 ng serve 生成的 index.html 不同,只包含對部分生成的 'es5' 腳本的引用。因此,應用程式在像 IE 11 這樣的 ES5 瀏覽器中無法正常運行。

到目前為止我有:

  • 確認該應用程式在像 Chrome 這樣的現代 ES2015+ 瀏覽器中運作正常
  • 在升級到 Angular 8 之前確認該應用程式在 IE 11 上可以運行
  • 將 IE 11 中的 index.html 原始碼與從 ng build 在 dist 目錄生成的原始碼進行比較,可以看到腳本引用的差異(見下面的範例程式碼)
  • 在 Github 和 Stack Overflow 上搜尋了有關 Angular 和 Angular-CLI 的問題,以尋找類似的問題
  • 嘗試在 angular.json 中有與沒有即將被棄用的 es5BrowserSupport 選項的情況下進行構建和服務
  • 已更新至 @angular-devkit 和 @angular 套件的最新版本

我正在處理的版本庫包含一個應用程式專案和一個函式庫專案。以下是在 Angular 8 升級後,angular.json 中的相關架構目標:

      "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"
            }
          }
        },

這是啟用 IE 11 支援的 browserlist 文件:

> 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
  },
}

預期結果

ng build 會在 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>

實際結果

ng serve 正在向 IE 11 提供一個只包含 ES5 版本 pollfills.js 的 index.html:

<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>

答案#1

經過一點更多的查找,我發現了 GitHub 上的這個討論,指出 ng serve 和 ng build --watch 預設情況下會關閉差異加載。這似乎是出於性能原因(差異加載需要執行兩個構建,ES5 和非 ES5)。有一個解決方法是使用 ES5 套件,而不是預設套件。

答案#2

那是你的程式碼的正確行為。Angular CLI 會檢測瀏覽器並在執行時注入 polyfill 腳本,如此這般。

所以如果你使用較舊版本的瀏覽器,你將會看到帶有 nomodule 標籤的腳本

你可以在這裡閱讀更多