-
Notifications
You must be signed in to change notification settings - Fork 1k
Add an external library to a web part
The SharePoint Framework is currently in Preview, and is subject to change based on customer feedback. While we’re in preview, SharePoint Framework web parts are not supported for use in production environments.
In your web part, you will likely want to include one or more JavaScript libraries.
Depending on your scenario, you would want to:
- Load a small library in a single web part?
- Share a library among multiple web part?
- Load a library from a CDN?
- Load a non-AMD script?
- [Load a library with a dependency on another library?] (#loading-a-library-that-has-a-dependency-on-another-library)
- [Load SharePoint JSOM?] (#loading-sharepoint-jsom)
- [Load a localized resource?] (#load-localized-resources)
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.
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');
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.
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__.'));
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.
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() );
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.
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);
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.
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 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');
Loading localized resources is simple. There is a map in config.json
called localizedResources
with which you can describe how to load localized resources. Paths in this map are relative to the lib
folder and must not contain a leading slash (/
).
In this example, we have a folder src/strings/
. In this folder are several JavaScript files with names such as en-us.js
, fr-fr.js
, de-de.js
. Because each of these files must be loadable by the module loader, they must contain a CommonJS wrapper. For example, in en-us.js
:
define([], function () {
var strings = {
webpartTitle: "My web part title",
initialPrompt: "Initial prompt",
exitPrompt: "Exit"
};
strings.default = strings;
return strings;
});
Edit the config.json
file. Add an entry to localizedResources
. The {locale}
is a placeholder token for the locale name:
{
"strings": "strings/{locale}.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);
-
Getting Started