Skip to Content
Technical Articles
Author's profile photo Vivek Chandregowda

Project Shims – Using NPM modules with UI5

Have you ever heard of ‚Shims‘?

Conventionally speaking, shim means a thin piece of material used for filling small gaps or spaces between objects. Typically these are used to provide better support and fit to an existing structure. In the tech world, ‚shim‚ has been used to refer to polyfills or libraries that help a particular software/code support a newer environment.

In this blog we are going to talk a bit more of tech and share about ‚Project Shims‘ in the context of ui5 tooling.

Shims in UI5

 

If you are aware about UI5 (OpenUI5/SAPUI5), then you already know that UI5 provides us a powerful development toolkit for developing apps. But it can’t provide everything and also it should not re-invent everything which already exists. Every framework solves this problem by using third party tools. Some of the popular examples are bootstrap library for responsive UI, lodash for JS utility functions, d3 for charts and diagrams etc. These third party libraries are shims which will help UI5 framework for building better apps.

Until UI5 Tooling came into picture, using third party libraries with UI5 was not easy as compared to other JavaScript frameworks. Some of the popular ways to use third party libraries in UI5 was,

  1. Using CDN script in index.html of the UI5 application.
  2. Downloading the library files and loading it in project.

A major issue with the above approach is that prevents us from using world’s largest software registry and the standard choice for JavaScript packages-  npm. NPM packages greatly help with easy installations and easy version management. This problem is now tackled in UI5 with the help of Project Shims. ?

A project shim extension can be used to define or extend a project configuration of a module. The most popular use case is probably to add UI5 project configuration to a third party module that otherwise could not be used with the UI5 Tooling.

The below part of blog assumes that you have a basic understanding about ui5-tooling and yarn. If not, then go through UI5 Tooling documentation and yarn documentation.

(1) Preparing a sample UI5 project:

If you don’t have a ui5-tooling based project with you, then just follow the below steps:

  1. Clone or download UI5 boilerplate project from ‚https://github.com/integrtr/ui5-boilerplate
  2. Install project dependencies using yarn install
  3. Run yarn start to start local development server. Once started you would be able to view your app running in default browser at http://localhost:8080

Voila! We have our ui5-starter-app built with the new ui5-tooling ready !

(2) Enhancing with NPM packages

Let’s add lodash and momentjs to our current project. You can do so by running the below commands in your terminal:

yarn add lodash
yarn add moment

UI5 tooling needs all dependencies to be maintained in ui5 > dependencies section of Package.json. Lets add that configuration to our Package.json. Below is how your final Package.json file should look like.

Tip: You can verify your dependencies using ui5 treecommand in the terminal

 

Now new modules should be maintained in ui5.yaml file. This can be done using UI5 tooling extension project-shim. At the end of your ui5.yaml file below code should be placed. Since we are adding a project extension, below code should be separated by new line with 3 dashes (- – -)

---
specVersion: '2.1'
kind: extension
type: project-shim
metadata:
  name: thirdparty # this can be your project shim name
shims:
  configurations:
    lodash: # name as defined in package.json
      specVersion: '2.1'
      type: module # Use module type
      metadata:
        name: lodash
      resources:
        configuration:
          paths:
            /resources/thirdparty/lodash/: ''  # location where modules are stored
    moment: # name as defined in package.json
      specVersion: '2.1'
      type: module # Use module type
      metadata:
        name: moment
      resources:
        configuration:
          paths:
            /resources/thirdparty/moment/: ''  # location where modules are stored

 

/resources/thirdparty/lodash will be the location inside dist folder where your modules will be stored. Location inside /resources/ folder can be customized further similar to /resources/<custom_folder_path>/. Same path will be used in controller and component file to import node modules.

Now we have our NPM modules and that should be imported in project. These can be imported in any JS file such as component or controller files. If you are using some package globally and need it as soon as you load application, then it is better to require in Component.js, otherwise it can be required in any controllers file.

Below is a sample controller file where we are using lodash and momentjs for demonstration purpose.

 

While importing you need to use the same path which was provided in ui5.yaml file after omitting /resources part. At the end of path NPM package JavaScript file name should be added. For example lodash.js is the file inside lodash folder. If you are having confusion with file name you can always build project using yarn build-all to view folder structure and find file name.

 

That’s it! Now go ahead and include your favorite npm packages inside your UI5 projects and make use of amazing third party libraries to build your awesome UI5 applications.

This article was originally published here.

Assigned Tags

      26 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Thomas Jung
      Thomas Jung

      The link in Step 1 to your github repo https://github.com/integrtr/ui5-boilerplate  seems to be broken.

      Author's profile photo Nitish Mehta
      Nitish Mehta

      Hey Thomas,
      We didn't realize it was private all this while. The repository has been made public now 🙂

      Cheers, Nitish

      Author's profile photo Julien DESPREZ
      Julien DESPREZ

      Hi Vivek,

       

      thank your for this very interesting article. I tried your technique but I am facing some issues :

       

      First one is, when I run the build command, I find my library into the ressources/thirdparty/<library name>/dist folder. Do you now how to get it directly into ressources/thirdparty/<library name> folder ?

      Second issue is deployment;to automate everything I use the ui5-task-nwabap-deployer custom task which is run by the ui5 tooling build command to upload the ui5 app to the abap server. Unfortunalty, only my ui5 app is uploaded by the task, do you think it's related to the custom task only ?

      Regards.

      julien

       

      Author's profile photo Julien DESPREZ
      Julien DESPREZ

      I am auto responding to myself.

       

      By setting the path correctly i can avoid having another dist folder :

                paths:
                  /lib/thirdparty/html2canvas/: "dist" # map root directory of module​

      For my second issue, I used another deployment tool that is not a builder custom task and ran it manually after the build phase.

      I finally ran into a third issue which is that my app could find the library because the cache buster mecanism add a timestamp into the url of the virtual folder resources. By removing the cache buster in my index.html the app works with the library.

      Maybe if someone has an idea on how to use the cache buster with thirdparty libraries.

       

      Author's profile photo aurelien albert
      aurelien albert

      Hi,

      Nice blog! How do you handle your lib during the development phase? via data-sap-ui-resourceRoots in index.html?

      At that point the references are not known yet as /resources/thirdparty are being created during the build phase…

      I’m using BAS as development environment

      Thanks

      Aurélien

      Author's profile photo Zayidu Ansari
      Zayidu Ansari

      Do you have a solution?

       

      I want to source the sap.ui.core library to

      https://sapui5.hana.ondemand.com/resources/sap-ui-core.js in index.html instead of adding it thru the CLI ui5 add sap.ui.core sap.m which consumes unnecessary memories for all projects.
      Doing this how can I apply it to ui5 build as well? Currently, it creates a file

      src="resources/sap-ui-custom.js" and results in the below errors.
      ERR! lbt:bundle:Resolver **** error: missing module sap/ui/model/json/JSONModel.js, required by xxxxx/model/models.js
      ERR! lbt:bundle:Resolver **** error: missing module sap/ui/Device.js, required by xxxxx/model/models.js
      ERR! lbt:bundle:Resolver **** error: missing module ui5loader-autoconfig.js, required by xxxxxxxx/model/models.js
      ERR! lbt:bundle:Resolver **** error: missing module sap/ui/core/mvc/Controller.js, required by xxxxxxxx/controller/Main.controller.js
      ERR! lbt:bundle:Resolver **** error: missing module sap/ui/core/UIComponent.js, required by xxxxxxxx/Component.js
      ERR! lbt:bundle:Resolver **** error: missing module sap/ui/core/library.js, required by xxxxxxxx/Component.js
      ERR! lbt:bundle:Resolver **** error: missing module sap/m/library.js, required by xxxxxxxx/Component.js
      ERR! lbt:bundle:Resolver **** error: missing module sap/ui/layout/library.js, required by xxxxxxxx/Component.js
      ERR! lbt:bundle:Resolver **** error: missing module sap/ushell/library.js, required by xxxxxxxx/Component.js
      ERR! lbt:bundle:Resolver **** error: missing module sap/collaboration/library.js, required by xxxxxxxx/Component.js
      ERR! lbt:bundle:Resolver **** error: missing module sap/ui/comp/library.js, required by xxxxxxxx/Component.js
      ERR! lbt:bundle:Resolver **** error: missing module sap/uxap/library.js, required by xxxxxxxx/Component.js
      ERR! lbt:bundle:Resolver **** error: missing module sap/ui/model/resource/ResourceModel.js, required by xxxxxxxx/Component.js
      ERR! lbt:bundle:Resolver **** error: missing module sap/ui/core/mvc/XMLView.js, required by xxxxxxxx/view/Main.view.xml
      Thanks, Zayid.
      Author's profile photo aurelien albert
      aurelien albert

      Hi,

       

      Not sure how it's related to my original question. Maybe best to put it in a separate question thread no? I got the same behavior but don't get those issue in my project.

       

      Kr

      Aurélien

      Author's profile photo aurelien albert
      aurelien albert

      I was probably doing something wrong, following the steps work even when testing locally...

      Author's profile photo Zayidu Ansari
      Zayidu Ansari

      Great Article! Thanks a lot for this.

       

      I have an issue though!

      Under dist/resources, it isn’t generating any thirdparty/{Libraries} folder on running yarn run build.

       

      What might be the possible error/config that I would have missed? Can you share your whole ui5.yaml code?

      Author's profile photo aurelien albert
      aurelien albert

      Hi,

       

      Try "ui5 build self-contained -a --clean-dest" command . It worked for me!

       

      Kr

      Aurélien

      Author's profile photo Zayidu Ansari
      Zayidu Ansari

      Thanks Aurelien,

       

      It worked.

      Author's profile photo Dhananjay Hegde
      Dhananjay Hegde

      I was facing the same issue and this worked.  thank you

      Author's profile photo Richard Brünning
      Richard Brünning

      Hi,

      somebody got it to work on local development via Visual Studio Code? In my dist folder everthing is there but in dev time the 3rd party lib is not build and loaded. What can i do?

      The ui5 loader seems always to look for the SAP CDN, the project shim config seems only to be relevant when I build the App.

       

      Short: 3rd Party library not found in local development mode

      Author's profile photo Zayidu Ansari
      Zayidu Ansari

      Of course, it wouldn't be there 'coz in packag.json you would have configured for the only dist folder to store the built files.

       

      One simple thing you can do is manually copy the resource folder from dist folder and put in the webapp dev folder and change the path in sap.ui.define to your absolute path, It will work as expected.

      Author's profile photo Richard Brünning
      Richard Brünning

      Thanks :), that is actually my solution at the moment.

      But I´m not that happy because of the copy source files.

      Is there a solution which loads the 3rd party modules in local dev (ui5 serve) like a full build on save or something like that?

      Author's profile photo Zayidu Ansari
      Zayidu Ansari

      You can yarn add or npm install the libs in resources/thirdparty folder.

      Author's profile photo Zayidu Ansari
      Zayidu Ansari

      Hello Guys,

       

      I am facing one issue. I had downloaded the ui5 objects from ABAP repo and I am using ui5-tooling to do the changes, I am editing and adding contents to the xml and in js files

      For eg: 

      • I added a debugger in onInit of one of the controller, the debugger isn’t getting triggered.
      • I added some new contents in xml or change the title in a Panel, still the changes are NOT getting reflected on live serve

      This means any new changes I do and save the files and when I check the new changes in the browser it isn’t getting reflected on live serve.

      Any solutions or any idea why this weirdness?

       

      Thanks a lot.

      Author's profile photo Zayidu Ansari
      Zayidu Ansari

      SOLUTION: 

      I deleted my Component-preload.js file and it worked fine.

      Author's profile photo aurelien albert
      aurelien albert

      Hello,

       

      I'm using the Shims to include 3rd party libraries in an app but when i want to deploy the app it fails with the error below!

      "Source contains multiple documents; please use YAML.parseAllDocuments()"

      Any idea?

      More details on https://answers.sap.com/questions/13359343/ui5-project-shims-deployment.html

      Thanks

      Aurélien

      Author's profile photo Vivek Chandregowda
      Vivek Chandregowda
      Blog Post Author

      Not sure about the exact error message. I will respond to question if I can find some solution  https://answers.sap.com/answers/13384418/view.html

      Author's profile photo Carsten Michels
      Carsten Michels

      Vivek Chandregowda Thanks for that great blog post!

      One question I got...I started my project in BAS with a fiori freestyle component... 

      So I need first to BUILD the app that I can use it with /ressource/thirdparty/ in my controller right? 

       

      Long story short: Can I use it while I am developing before I build the app and use it in my local runtime?

       

      Author's profile photo Vivek Chandregowda
      Vivek Chandregowda
      Blog Post Author

      yes, you should be able to use while developing. But it would be easy to debug if there are any issues, if you build once and test.

      Author's profile photo Carsten Michels
      Carsten Michels

      I think i did everything like you do but getting the following error?!

       

      Uncaught (in promise) ModuleError: Failed to resolve dependencies of 'tsys/magentadaoapp/controller/View1.controller.js'
       -> 'thirdparty/moment/moment.js': failed to load 'thirdparty/moment/moment.js' from resources/thirdparty/moment/moment.js: script load error
          at p1 (https://workspaces-ws-gbgbv-app2.eu20.applicationstudio.cloud.sap/resources/sap-ui-core.js:53:213)
          at j1.failWith (https://workspaces-ws-gbgbv-app2.eu20.applicationstudio.cloud.sap/resources/sap-ui-core.js:40:43)
          at https://workspaces-ws-gbgbv-app2.eu20.applicationstudio.cloud.sap/resources/sap-ui-core.js:65:1556
      Caused by: ModuleError: failed to load 'thirdparty/moment/moment.js' from resources/thirdparty/moment/moment.js: script load error
          at p1 (https://workspaces-ws-gbgbv-app2.eu20.applicationstudio.cloud.sap/resources/sap-ui-core.js:53:213)
          at j1.failWith (https://workspaces-ws-gbgbv-app2.eu20.applicationstudio.cloud.sap/resources/sap-ui-core.js:40:43)
          at HTMLScriptElement.p (https://workspaces-ws-gbgbv-app2.eu20.applicationstudio.cloud.sap/resources/sap-ui-core.js:60:468)
      Caused by: Error: script load error
          at HTMLScriptElement.p (https://workspaces-ws-gbgbv-app2.eu20.applicationstudio.cloud.sap/resources/sap-ui-core.js:60:510)
      Author's profile photo CARLOS AUGUSTO GUZMÁN PÉREZ
      CARLOS AUGUSTO GUZMÁN PÉREZ

      Hi Carsten,

      I faced a somewhat similar problem, the solution for me was changing the "src" in the "index.html" to src="resources/sap-ui-core.js" instead of CDN.

      Author's profile photo Dhananjay Hegde
      Dhananjay Hegde

      Hi Vivek

      Thanks for the great post.  Before finding this I had no clue about UI5 tooling and now I learnt a lot.

      I wanted to import some third-party modules and was not sure how to do it.  This helped me a lot!

      Thank you,

      Dhananjay

      Author's profile photo Jacky Liu
      Jacky Liu

      Hi,Vivek,

       

      I used this method in a easy-ui5 generated project and deploy to BTP cloud foundry runtime . The file third-party folder resources . But when run locally , an error shows like the following .

       

      You help would be greatly appreciated !

       

      Best Regards!

       

      Jacky Liu

       

       

      the tsconfig.json

      {
      "compilerOptions": {
      "module": "AMD",
      "noEmit": true,
      "checkJs": true,
      "allowJs": true,
      "types": [
      "@sapui5/ts-types"
      ],
      "lib": [
      "es2015"
      ]
      }
      }