Reputation: 10879
Short Version
I want to know the correct way to import UIkit into a SharePoint SPFx web part.
I can successfully import jQuery like this:
In config.json
, I specify the link to the library:
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"
I import the relevant ‘types’:
npm install --save-dev @types/jquery
In my_web_part.ts
, I import the library and then use it:
import * as $ from 'jquery';
// .....
<div id="jquery-test">Hello, jQuery!</div>
$('#jquery-test').text('jQuery is working!');
But when I try and import UIkit in the same way, ie:
In config.json
:
"uikit": "https://cdnjs.cloudflare.com/ajax/libs/uikit/3.21.5/js/uikit.min.js",
"uikit-icons": "https://cdnjs.cloudflare.com/ajax/libs/uikit/3.21.5/js/uikit-icons.min.js"
Import the relevant ‘types’:
npm install --save-dev @types/uikit
In my_web_part.ts
:
import * as UIkit from 'uikit';
// ...
<a href="#" uk-icon="heart"></a>
<div uk-slider="autoplay: true" id="my_slider">
<div class="uk-slider-container">
<!-- Slider items here -->
</div>
</div>
the result is that:
If I try and reference UIkit explicity like this, I can see that UIkit is not available:
UIkit.slider('#my_slider')
It is like UIKit is not even imported into the file.
Long Version
I have followed the instructions here:
My config.json
file looks like this:
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/config.2.0.schema.json",
"version": "2.0",
"bundles": {
"my-custom-html-interface-web-part-web-part": {
"components": [
{
"entrypoint": "./lib/webparts/myCustomHtmlInterfaceWebPart/MyCustomHtmlInterfaceWebPartWebPart.js",
"manifest": "./src/webparts/myCustomHtmlInterfaceWebPart/MyCustomHtmlInterfaceWebPartWebPart.manifest.json"
}
]
}
},
"externals": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js",
"uikit": "https://cdnjs.cloudflare.com/ajax/libs/uikit/3.21.5/js/uikit.min.js",
"uikit-icons": "https://cdnjs.cloudflare.com/ajax/libs/uikit/3.21.5/js/uikit-icons.min.js"
},
"localizedResources": {
"MyCustomHtmlInterfaceWebPartWebPartStrings": "lib/webparts/myCustomHtmlInterfaceWebPart/loc/{locale}.js"
}
}
I have installed the required 'types':
npm install --save-dev @types/jquery
npm install --save-dev @types/uikit
This is one of the many versions of code I have tried in my 'webpart.ts' file:
/* eslint-disable */
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
import * as $ from 'jquery';
import * as UIkit from 'uikit';
export default class MyCustomHtmlInterfaceWebPart extends BaseClientSideWebPart<{}> {
public render(): void {
this.domElement.innerHTML = `
<div id="jquery-test">Hello, jQuery!</div>
<a href="#" uk-icon="heart"></a>
<div uk-slider="autoplay: true" id="my_slider">
<div class="uk-slider-container">
<!-- Slider items here -->
</div>
</div>
`;
// jQuery usage
$('#jquery-test').text('jQuery is working!');
if (UIkit) {
// UIkit usage
(UIkit as any).slider('#my_slider', {})
console.log("THIS IS GOOD");
}
else {
console.log("THIS IS BAD"); // <-- this is logged, because it can't find UIkit
}
}
}
I am new to SharePoint SPFx, TypeScript and ESLint so I am not clear what and where the actual problem is.
I created the project like this:
yo @microsoft/sharepoint
And answered the prompts like this:
Solution Name: MyWebpartName
Client-side component: WebPart
Web part name: MyWebpartName
Framework: No framework
My package.json
looks like this:
{
"name": "my-custom-html-interface-web-part",
"version": "0.0.1",
"private": true,
"engines": {
"node": ">=18.17.1 <19.0.0"
},
"main": "lib/index.js",
"scripts": {
"build": "gulp bundle",
"clean": "gulp clean",
"test": "gulp test"
},
"dependencies": {
"@microsoft/sp-component-base": "1.19.0",
"@microsoft/sp-core-library": "1.19.0",
"@microsoft/sp-lodash-subset": "1.19.0",
"@microsoft/sp-office-ui-fabric-core": "1.19.0",
"@microsoft/sp-property-pane": "1.19.0",
"@microsoft/sp-webpart-base": "1.19.0",
"tslib": "2.3.1"
},
"devDependencies": {
"@fluentui/react": "^8.106.4",
"@microsoft/eslint-config-spfx": "1.20.1",
"@microsoft/eslint-plugin-spfx": "1.20.1",
"@microsoft/rush-stack-compiler-4.7": "0.1.0",
"@microsoft/sp-build-web": "1.20.1",
"@microsoft/sp-module-interfaces": "1.20.1",
"@rushstack/eslint-config": "2.5.1",
"@types/jquery": "^3.5.30",
"@types/uikit": "^3.14.5",
"@types/webpack-env": "~1.15.2",
"ajv": "^6.12.5",
"eslint": "8.7.0",
"gulp": "4.0.2",
"typescript": "4.7.4"
}
}
I use nvm
with Node version 18.17.1
.
I have checked the SPFx/Node compatability chart here and all looks OK:
https://learn.microsoft.com/en-us/sharepoint/dev/spfx/compatibility
I use these commands to build and test in workbench:
gulp clean
gulp bundle --ship
gulp package-solution --ship
gulp serve --nobrowser
And then I go to this URL to access the workbench:
https://<organisation-tenant>.sharepoint.com/_layouts/15/workbench.aspx
where the tenant uses SharePoint Online.
(The workbench behaviour seems really slow, buggy and inconsistent. I am not sure how often the workbench is being refreshed and there are always lots of errors in the chrome dev tools console, even before I add my webpart there).
Other References:
Add an external library to your SharePoint client-side web part
https://learn.microsoft.com/en-us/sharepoint/dev/spfx/web-parts/basics/add-an-external-library
Use existing JavaScript libraries in SharePoint Framework client-side web parts
https://learn.microsoft.com/en-us/sharepoint/dev/spfx/web-parts/guidance/use-existing-javascript-libraries
Upvotes: 0
Views: 101
Reputation: 10879
I am just posting this answer as I seem to have got it working.
And I don't want to waste anyone's time if they were going to post a similar answer.
As I mentioned in the OP, I am very new to all these things:
So, as a disclaimer, the following information may not be best practice, or accurate.
I just don't have the knowledge to know if it is or not.
The result of all the information below is that:
in both the hosted workbench and production environment.
Learnings
UIkit and UIkit icons could NOT be imported into the webpart file if I referenced them in the externals
object in config.json
I think this is because the UIkit library is an ES module
, and not a UMD module
I therefore needed to npm install [email protected]
(the version of UIkit I wanted to use) so that the SPFx build process would bundle UIkit into the format that it requires it (which I think is UMD)
This means that I have to take the 'bundling' approach, as opposed to the 'linking to a CDN' approach, which will increase file download size if I were to use UIkit
in more than one webpart
I have to run a gulp clean
, gulp build
and gulp package-solution
after each code change and open the hosted workbench in a new tab at https://<tenant-name>.sharepoint.com/_layouts/15/workbench.aspx
because I found the workbench just doesn't reload the new code otherwise, or doesn't load the workbench UI properly (apparently there used to be a 'local' workbench that looked and performed better, but that does not exist anymore)
Setup
01) Contents of /config/config.json
(i added the jQuery externals property):
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/config.2.0.schema.json",
"version": "2.0",
"bundles": {
"custom-home-page-web-part": {
"components": [
{
"entrypoint": "./lib/webparts/customHomePage/CustomHomePageWebPart.js",
"manifest": "./src/webparts/customHomePage/CustomHomePageWebPart.manifest.json"
}
]
}
},
"externals": {
"jquery": {
"path": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js",
"globalName": "jQuery"
},
},
"localizedResources": {
"CustomHomePageWebPartStrings": "lib/webparts/customHomePage/loc/{locale}.js"
}
}
02) I installed the jQuery 'types' with:
npm install --save-dev @types/jquery
03) I did not install the uikit types, because that package is over 6 months old, so I though the type information may not be in sync with the latest UIkit version
04) Contents of tsconfig.json
(i added reference to new declaration files):
{
"extends": "./node_modules/@microsoft/rush-stack-compiler-4.7/includes/tsconfig-web.json",
"compilerOptions": {
"target": "es5",
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"jsx": "react",
"declaration": true,
"sourceMap": true,
"experimentalDecorators": true,
"skipLibCheck": true,
"outDir": "lib",
"inlineSources": false,
"noImplicitAny": true,
"typeRoots": [
"./node_modules/@types",
"./node_modules/@microsoft"
],
"types": [
"webpack-env"
],
"lib": [
"es5",
"dom",
"es2015.collection",
"es2015.promise"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.d.ts" // <---- I added this, it didn't work if i created a 'my_custom_types' folder in root package directory and referenced it in the 'typeRoots' property
]
}
05) I created two 'declaration files' in /src
:
uikit.d.ts
with this content:declare module 'uikit';
uikit-icons.d.ts
with this content:declare module 'uikit/dist/js/uikit-icons';
06) Contents of my webpart file (note the syntax used in the import statements etc):
/* eslint-disable */
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
import { SPComponentLoader } from '@microsoft/sp-loader';
import * as $ from 'jquery';
import UIkit from 'uikit';
import Icons from 'uikit/dist/js/uikit-icons';
UIkit.use(Icons);
export default class MyCustomHtmlInterfaceWebPart extends BaseClientSideWebPart<{}> {
public render(): void {
SPComponentLoader.loadCss('https://cdnjs.cloudflare.com/ajax/libs/uikit/3.21.11/css/uikit.min.css');
this.domElement.innerHTML = `
<div id="jquery-test">Hello, jQuery!</div>
<a href="#" uk-icon="heart"></a>
<div uk-slider="autoplay: true" id="my_slider">
<div class="uk-slider-container">
<!-- Slider items here -->
</div>
</div>
`;
// jQuery usage
$('#jquery-test').text('jQuery is working!');
// UIkit usage with 10-second timeout
setTimeout(() => {
if (UIkit) {
// Test a simple UIkit notification to see if UIkit is loaded
(UIkit as any).notification('UIkit is working!', { status: 'success' });
// Try initializing the slider
(UIkit as any).slider('#my_slider', {});
console.log("THIS IS GOOD");
} else {
console.log("THIS IS BAD");
}
}, 10000); // 10 seconds timeout
}
}
Upvotes: 0