SharePoint Framework 在web部件中使用已存在的JavaScript庫 - 捆綁打包和外部引用

Justin-Liu發表於2018-01-22

部落格地址:http://blog.csdn.net/FoxDave

在構建SPFx客戶端web部件時,你可以使用公網已有的JavaScript庫來構建強大的解決方案。但是在使用的時候你需要考慮你引用的東西沒有影響SharePoint頁面的效能。

以包的形式引用已存在的庫

引用已存在的JavaScript庫的通常方式是以包的形式安裝到專案中。拿Angular舉例,首先在專案中安裝它的包:

npm install angular --save

接下來通過TypeScript使用Angular,需要安裝型別:

npm install @types/angular --save

最後,在你的web部件中引用Angular,使用import宣告:

import { Version } from '@microsoft/sp-core-library';
import {
  BaseClientSideWebPart,
  IPropertyPaneConfiguration,
  PropertyPaneTextField
} from '@microsoft/sp-webpart-base';
import { escape } from '@microsoft/sp-lodash-subset';

import styles from './HelloWorld.module.scss';
import * as strings from 'helloWorldStrings';
import { IHelloWorldWebPartProps } from './IHelloWorldWebPartProps';

import * as angular from 'angular';

export default class HelloWorldWebPart extends BaseClientSideWebPart<IHelloWorldWebPartProps> {
  public render(): void {
    this.domElement.innerHTML = `
      <div class="${styles.helloWorld}">
        <!-- omitted for brevity -->
      </div>`;

      angular.module('helloworld', []);

      angular.bootstrap(this.domElement, ['helloworld']);
  }

  // omitted for brevity
}
打包web部件資源

SPFx使用基於開源的工具鏈進行編譯,如gulp和Webpack。在編譯SPFx專案時,這些編譯工具會在一個叫做bundling的程式中自動將所有引用的資源打包到一個單一的JavaScript檔案中。這種方式有很多優點。首先,所有web部件需要的資源都在一個單一的JavaScript檔案中可用。這簡化了web部件的部署步驟,不容易產生遺漏。由於你的web部件使用了不同的資源,以正確的順序逐個載入是很重要的。同時這種方式也對終端使用者有益。一般來說,下載一個較大的單一檔案要比下載好多小檔案要快,進而你的web部件也會在頁面上更快地完成載入。

然而這種方式也有一些不足。在編譯SPFx中已存在的JavaScript框架時,所有引用的指令碼都被包含在生成的單一檔案中,以Angular為例,這個生成後的檔案有170KB。


如果你在專案中再新增一個也使用Angular的web部件,在編譯後你會發現有兩個170KB的檔案。這樣當你在頁面中同時新增這兩個web部件的時候,就會載入兩次同樣內容的較大的指令碼檔案,這嚴重影響了效能。

作為外部資源引用已存在的庫

一個更好的引用已存在的庫的實現方式是作為外部資源進行引用。這樣在web部件中就只有一個指令碼的URL就夠了,其實跟web頁面的編寫是一個意思,在頁面載入的時候會自動去載入指定URL的資源。

這種方式也不需要進行包的安裝,但是需要安裝型別:

npm install @types/angular --save

接下來在config/config.json檔案中的externals屬性中加入一條:

"angular": {
  "path": "https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js",
  "globalName": "angular"
}
完整的檔案內容大致如下所示:
{
  "entries": [
    {
      "entry": "./lib/webparts/helloWorld/HelloWorldWebPart.js",
      "manifest": "./src/webparts/helloWorld/HelloWorldWebPart.manifest.json",
      "outputPath": "./dist/hello-world.bundle.js"
    }
  ],
  "externals": {
    "angular": {
      "path": "https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js",
      "globalName": "angular"
    }
  },
  "localizedResources": {
    "helloWorldStrings": "webparts/helloWorld/loc/{locale}.js"
  }
}
最後,在你的web部件中引用Angular就可以了,跟之前沒什麼區別:

import { Version } from '@microsoft/sp-core-library';
import {
  BaseClientSideWebPart,
  IPropertyPaneConfiguration,
  PropertyPaneTextField
} from '@microsoft/sp-webpart-base';
import { escape } from '@microsoft/sp-lodash-subset';

import styles from './HelloWorld.module.scss';
import * as strings from 'helloWorldStrings';
import { IHelloWorldWebPartProps } from './IHelloWorldWebPartProps';

import * as angular from 'angular';

export default class HelloWorldWebPart extends BaseClientSideWebPart<IHelloWorldWebPartProps> {
  public render(): void {
    this.domElement.innerHTML = `
      <div class="${styles.helloWorld}">
        <!-- omitted for brevity -->
      </div>`;

      angular.module('helloworld', []);

      angular.bootstrap(this.domElement, ['helloworld']);
  }

  // omitted for brevity
}
再次編譯你的專案你會發現這次的大小隻有6KB。


如果你再新增一個web部件,那麼就會生成兩個大小為6KB的檔案。說到這裡大家可能會有疑問,這實際上就是大小變了而已,但是並沒改變載入檔案的數量。其實不是的,前一種方式是將要引用的庫一起打包到了JS檔案中,實際上相當於載入了兩次;而對於外部引用這種方式,外部的資源如Angular只載入一次,並且得益於快取機制,外部引用的資源很可能已經在使用者訪問你的web部件時載入好了,這麼看確實是提高了效能。

相關文章