Skip to content

Add an external library to a web part

Nicholas Pape edited this page Aug 17, 2016 · 10 revisions

Introduction

In your web part, you will likely want to include one or more JavaScript libraries.

Depending on your scenario, you would want to:

Bundling a script

By default, the web part bundler will automatically include any library that is a dependency of the web part module. This means the library will be deployed in the same JavaScript bundle file as your web part. This is more useful for smaller libraries that are not used in multiple WebParts.

Example

Let's include the validator package which is string validator library into a we part.

To start with, we first download the validator package from npm:

npm install validator --save

Since TypeScript is our main programming language, we also require typings for the package you add. This is essential when you are writing code as TypeScript is just a superset of JavaScript. All of the TypeScript code is still converted to JavaScript code when you compile.

Normally, you would search and find typings using tsd package, for example:

tsd install {package} --save

However, it is quite possible that some libraries do not have typings. Validator is one of them. In this case you would want to define your own typings definition .d.ts file for the library. An incomplete example for the validator library is below.

Create a file in the your WebPart's folder called validator.d.ts and add the following:

declare module "validator" {
  export function isEmail(email: string): boolean;
  export function isAscii(text: string): boolean;
}

In your web part file, then import the typings:

import * as validator from 'validator';

Once the typings are imported, then you can use the validator library in your web part code:

validator.isEmail('foo@bar.com');

Sharing a library among multiple WebParts

In many cases your client-side solution may include multiple web parts. And often, these web parts will need to import or share the same library. In such cases, instead of bundling the library, you should include it in a separate JavaScript file to improve performance and caching. This is especially true of larger libraries.

Example

In this example we will share the marked package - a Markdown compiler - in a separate bundle.

First, download marked package from npm:

npm install marked --save

Download the typings:

tsd install marked --save

To not bundle this library with your web part bundle, edit the config/config.json and add an entry to the externals map. This is what tells the bundler to put this in a separate file.

"marked": "node_modules/marked/marked.min.js"

Now that we have added the package and typings for the library, add the statement to import the marked library in your web part:

import * as marked from 'marked';

Now you can use the library in your web part:

console.log(marked('I am using __markdown__.'));

Loading a script from a CDN

Instead of loading the library from a npm package, you would just want to load a script from a CDN. To do so, you will edit the config.json file to load the library from its CDN URL.

Example

In this example, we will load jQuery from CDN.

AS we are loading the library from CDN, we do not need to install the npm package. However, we still need to install the typings. In our case, lets install the typings for jQuery:

tsd install jquery --save

Update the config.json in the config folder to load jQuery from CDN. Add an entry to the externals field:

"jquery": "https://code.jquery.com/jquery-3.1.0.min.js"

Now import jQuery in your web part:

import * as $ from 'jquery';

And use it in your web part:

alert( $('#foo').val() );

Loading a non-AMD module

Some scripts follow the legacy JavaScript pattern of storing the library on the global namespace. This pattern is now deprecated in favor of Universal Module Definitions (UMD)/Asynchronous Module Definitions (AMD) or ES6 modules. However, it is possible that you have the need to load such libraries in your web part.

In order to load a non-AMD module, you add an additional property to the entry in your config.json file.

Example

In this example we will load a fictional non-AMD module from Contoso's CDN. However, these steps would apply for any non-AMD script in your src/ or node_modules/ directory.

The script is called Contoso.js and is stored at `https://contoso.com/contoso.js'. It's contents are:

var ContosoJS = {
  say: function(text) { alert(text); },
  sayHello: function(name) { alert('Hello, ' + name + '!'); }
};

Now, create typings for the script in a file called contoso.d.ts in the WebPart folder.

declare module "contoso" {
    interface IContoso {
      say(text: string): void;
      sayHello(name: string): void;
    }
    var contoso: IContoso;
    export = contoso;
}

Now update the config.json file to include this script. Add an entry to the externals map:

{
 "contoso": {
    "path": "https://contoso.com/contoso.js",
    "globalName": "ContosoJS"
  }
}

Add an import to your WebPart code:

import contoso from 'contoso';

Now you can use the contoso library in your code:

contoso.sayHello(username); 

Loading a library that has a dependency on another library

Many libraries have dependencies on another library. You can specify such dependencies in the config.json file using the globalDependencies property.

Note that there is no need to specify this field for non-AMD modules, as they will properly import each other. However, it is important to note that a non-AMD module have a AMD module as a dependency.

There are two examples of this.

Non-AMD module has a non-AMD module dependency

In this case we have 2 fictional scripts. These are in our src/ folder, although they could also be loaded from a CDN.

ContosoUI.js

Contoso.EventList = {
    alert: function() {
        var events = Contoso.getEvents();
        events.forEach( function(event) {
            alert(event);
        });
    }
}

ContosoCore.js

var Contoso = {
    getEvents: function() {
        return ['A', 'B', 'C'];   
    }
};

Add or create tpyings for this class. In this case, we will create Contoso.d.ts, which contains typings for both JavaScript files.

contoso.d.ts

declare module "contoso" {
  interface IEventList {
    alert(): void;
  }
  interface IContoso {
    getEvents(): string[];
    EventList: IEventList;
  }
  var contoso: IContoso;
  export = contoso;
}

Update the config.json file. Add two entries to externals:

{
        "contoso": {
            "path": "/src/ContosoCore.js",
            "globalName": "Contoso"
        },
        "contoso-ui": {
            "path": "/src/ContosoUI.js",
            "globalName": "Contoso",
            "globalDependencies": ["contoso"]
        }
}

Add imports for Contoso and ContosoUI

import contoso = require('contoso');
require('contoso-ui');

Use the libraries in your code:

contoso.EventList.alert();

Loading SharePoint JSOM

Loading SharePoint JSOM is essentially the same scenario as loading non-AMD scripts which have dependencies. This means utilizing both the globalName and globalDependency options.

First, install typings for the JSOM

tsd install sharepoint --save

Add entries to the config.json:

{
  "sp-init": {
    "path": "https://CONTOSO.sharepoint.com/_layouts/15/init.js",
    "globalName": "$_global_init"
  },
  "microsoft-ajax": {
    "path": "https://CONTOSO.sharepoint.com/_layouts/15/MicrosoftAjax.js",
    "globalName": "Sys",
    "globalDependencies": [ "sp-init" ]
  },
  "sp-runtime": {
    "path": "https://CONTOSO.sharepoint.com/_layouts/15/SP.Runtime.js",
    "globalName": "SP",
    "globalDependencies": [ "microsoft-ajax" ]
  },
  "sharepoint": {
    "path": "https://CONTOSO.sharepoint.com/_layouts/15/SP.js",
    "globalName": "SP",
    "globalDependencies": [ "sp-runtime" ]
  }
}

In your WebPart, add the require statements:

require('sp-init');
require('microsoft-ajax');
require('sp-runtime');
require('sharepoint');

Load localized resources

Loading localized resources is simple. There is a map in config.json called localizedScripts with which you can describe how to load localized resources.

In this example, we have a folder src/strings/. In this folder are several TypeScript files with names such as en-us.ts, fr-fr.ts, de-de.ts. Each file exports an object such as:

Edit the config.json file. Add an entry to localizedScripts:

{
  "strings": "/lib/${culture}.js"
}

Add typings for your strings. In this case, we have a file MyStrings.d.ts:

    declare module "strings" {
        interface IStrings {
            webpartTitle: string;
            initialPrompt: string;
            exitPrompt: string;
        }
        var strings: IStrings;
        export default strings;
    }

Add imports for the strings in your project:

import strings from 'strings';

Use the strings in your project:

 alert(strings.initialPrompt);
Clone this wiki locally