Angular CLI 7.3 使用 ES2015 的 nomodule 屬性載入 Polyfills 函式庫

栏目: JavaScript · 发布时间: 6年前

内容简介:最近推出的在 Angular CLI 所建立的專案下,都有個
Angular CLI 7.3 使用 ES2015 的 nomodule 屬性載入 Polyfills 函式庫

最近推出的 Angular CLI 7.3 版本,新增了一個相當亮眼的特性。當你的 Angular 應用程式同時要符合 IE 或舊版瀏覽器時,以往都會用 Polyfill 來填充缺少的 HTML5/JS APIs,但這件事到了 Angular CLI 7.3 又變得更貼心了。不但如此,這個新特性一樣可以用在各種 SPA 框架中,像是 Vue, React 或其他函式庫也都可以套用相同技巧。欲知詳情請繼續看下去。

Angular CLI 7.3 使用 ES2015 的 nomodule 屬性載入 Polyfills 函式庫

關於 polyfills.ts 檔案

在 Angular CLI 所建立的專案下,都有個 src/polyfills.ts 檔案,裡面可以讓你設定需要載入哪些必要的 Polyfills 函式庫,好讓你的網站也可以支援舊版瀏覽器執行。

目前 Angular 支援的 Polyfills APIs 最低可支援到 IE9 瀏覽器!

Angular CLI 內建的 Polyfills 定義一直在進化,幾乎每一個大版都會有些更貼心的設計出現,我們來看看最近幾版的變化與差異。

關於 Angular CLI 6 的 polyfills.ts 檔案

如果你用 Angular CLI 6 建立的 Angular 專案,其預設的 src/polyfills.ts 檔案內容如下。註解中詳細說明了使用的時機點,想支援哪個瀏覽器就要匯入必要的 Polyfill 模組,有些模組需要額外透過 npm 進行安裝,記得要安裝之後才能使用。

/**
 * 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 is divided into 2 sections:
 *   1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
 *   2. Application imports. Files imported after ZoneJS that should be loaded before your main
 *      file.
 *
 * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
 * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
 * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
 *
 * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
 */

/***************************************************************************************************
 * 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';

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

// (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__BLACK_LISTED_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.
 */
import 'zone.js/dist/zone'; // Included with Angular CLI.

/***************************************************************************************************
 * APPLICATION IMPORTS
 */

關於 Angular CLI 7 的 polyfills.ts 檔案

我在 Angular Taiwan 2018 技術大會的【 Angular 7 全新功能探索 】演講中曾經分享過關於 Polyfills 的改進。但我們先來看一下這個版本預設的 src/polyfills.ts 檔案內容:

/**
 * 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 is divided into 2 sections:
 *   1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
 *   2. Application imports. Files imported after ZoneJS that should be loaded before your main
 *      file.
 *
 * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
 * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
 * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
 *
 * Learn more in https://angular.io/guide/browser-support
 */

/***************************************************************************************************
 * BROWSER POLYFILLS
 */

/** IE9, IE10, IE11, and Chrome <55 requires all of the following polyfills.
 *  This also includes Android Emulators with older versions of Chrome and Google Search/Googlebot
 */

// 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';

/**
 * 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__BLACK_LISTED_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.
 */
import 'zone.js/dist/zone'; // Included with Angular CLI.

/***************************************************************************************************
 * APPLICATION IMPORTS
 */

大部分內容都是一樣的,除了有些註解說明有調整外,主要是有一行不見了!

/** 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';

原本在 Angular CLI 6 之前有一個 reflect-metadata 套件預設被載入,但此套件只有執行在 JIT 模式的時候才需要,一般來說我們都會用 AOT 模式建置專案,因此這個檔案經常需要「手動」註解掉,但很多人不知道這個細節,導致這個檔案一直被額外載入,浪費了 20.7KB 左右的下載流量。

從 Angular CLI 7.0 開始,這項設定已經被拿掉,改由 ng build 的過程透過 webpack 全自動判斷是否加入,相當貼心的設計!

關於 Angular CLI 7.3 的 polyfills.ts 檔案

從 Angular CLI 7.3 開始,其預設的 src/polyfills.ts 檔案內容如下:

/**
 * 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 is divided into 2 sections:
 *   1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
 *   2. Application imports. Files imported after ZoneJS that should be loaded before your main
 *      file.
 *
 * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
 * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
 * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
 *
 * Learn more in https://angular.io/guide/browser-support
 */

/***************************************************************************************************
 * BROWSER POLYFILLS
 */

/** IE10 and IE11 requires the following for NgClass support on SVG elements */
// import 'classlist.js';  // Run `npm install --save classlist.js`.

/**
 * 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__BLACK_LISTED_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.
 */
import 'zone.js/dist/zone'; // Included with Angular CLI.

/***************************************************************************************************
 * APPLICATION IMPORTS
 */

這個版本就更激進了,直接拿掉以下內容:

/** IE9, IE10, IE11, and Chrome <55 requires all of the following polyfills.
 *  This also includes Android Emulators with older versions of Chrome and Google Search/Googlebot
 */

// 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 the Reflect API. */
// import 'core-js/es6/reflect';

不過各位不用擔心,並不是說從此不支援 IE9 ~ IE11,而是有新的設計出現,叫做 Conditional ES5 Browser Polyfill Loading

條件式 ES5 瀏覽器相容套件載入機制

全新的 Angular CLI 7.3 在 angular.json 設定檔中增加了一條選項設定 "es5BrowserSupport": true

"build": {
  "builder": "@angular-devkit/build-angular:browser",
  "options": {
    "outputPath": "dist/demo1",
    "index": "src/index.html",
    "main": "src/main.ts",
    "polyfills": "src/polyfills.ts",
    "tsConfig": "src/tsconfig.app.json",
    "assets": [
      "src/favicon.ico",
      "src/assets"
    ],
    "styles": [
      "src/styles.css"
    ],
    "scripts": [],
    "es5BrowserSupport": true
  },
  "configurations": {
    "production": {
      "fileReplacements": [
        {
          "replace": "src/environments/environment.ts",
          "with": "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"
        }
      ]
    }
  }
},

如果從舊版升級上來,記得要手動調整 src/polyfills.tsangular.json 的選項設定!( schema.json )

這個 "es5BrowserSupport" 選項如果設定為 true 的話,當你使用 ng buildng build --prod 的時候就會自動自動幫你打包上述這幾個 Polyfills 到一個獨立的 JS 檔案中,檔名為 es2015-polyfills.*****.js

但真正的重點在於這個檔案的載入方式,請看一下 ng build --prod 完後後建置出來的 index.html 檔案內容:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Demo1</title>
    <base href="/" />

    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link rel="icon" type="image/x-icon" href="favicon.ico" />
    <link rel="stylesheet" href="styles.3ff695c00d717f2d2a11.css" />
  </head>

  <body>
    <app-root></app-root>

    <script
      type="text/javascript"
      src="runtime.b57bf819d5bdce77f1c7.js"
    ></script>
    <script
      type="text/javascript"
      src="es2015-polyfills.41976a8133a2445ac0d9.js"
      nomodule
    ></script>
    <script
      type="text/javascript"
      src="polyfills.fb4ac03bdf7e23477d5b.js"
    ></script>
    <script type="text/javascript" src="main.e42ec0deb336589a6946.js"></script>
  </body>
</html>

看到亮點了嗎?

這裡的 es2015-polyfills.*****.js 檔案被載入時,被加上了 nomodule 屬性。這個屬性只有在支援 ES2015 的瀏覽器才認得,這些現代化的瀏覽器只要看見 <script> 標籤使用了 nomodule 屬性,就會自動忽略這個 JS 檔案載入,並不是載入後不執行,而是連載入動作都不會發生,大幅節省頻寬!(約 56K 左右)

但是 IE 或其他舊版瀏覽器,並不認得 nomodule 屬性,所以檔案就還是會載入並執行。如此一來,就徹底解決了跨瀏覽器相容的問題,是不是相當漂亮!

Safari 10.1 不支援 nomodule 的問題

目前已知 支援 ES2015 模組化技術 的瀏覽器版本如下:

  • Safari 10.1+
  • Chrome 61+
  • Firefox 60+
  • Edge 16+

不過 Safari 10.1 卻不支援 nomodule 屬性,解決方法可以參考 Safari 10.1 nomodule support 這個 Polyfills 來解決。這份 Polyfills 有詳細註解說明方式,請看仔細再加入到你的現有專案中!

相關連結


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

PHP and MySQL Web Development

PHP and MySQL Web Development

Luke Welling、Laura Thomson / Sams / July 25, 2007 / $49.99

Book Description PHP and MySQL Web Development teaches you to develop dynamic, secure, commerical Web sites. Using the same accessible, popular teaching style of the three previous editions, this b......一起来看看 《PHP and MySQL Web Development》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具