Skip to Content
Technical Articles

Using UI5 Libraries in CF approuter

With SCP Neo almost being deprecated, more and more developers are making the move to SCP CloudFoundry. Some may have already a lot of experience with CF but many things are not clear to everyone, at least not yet ? .

One of the things I faced was the usage of UI5 libraries. As a UI5 developer for several years now, I like to make everything as reusable as possible. In that case, UI5 libraries are the key. In this blog I’m going to share the challenges that I’ve faced and how to solve them.

Before we start, I want to thank Yuval and his team for the big help to make this work!

Create the UI5 library

First step is to create the UI5 Library. Currently there is no official UI5 Library template for CloudFoundry in Yeoman nor in the Business Application Studio available. (Correct me if I’m wrong here ? )

Instead I used the UI5 Freestyle template in the BAS:

In this template I used “SAPUI5 Application” to be able to go through the wizard:

For my example I used the Central AppRouter:

You need to provide a unique name which will be used to generate a unique url in the Central Approuter.

In case you would add the library in the same mta as the consuming UI5 app, you need to use the same id for both modules.

But it’s better to keep the library in a separate mta because it’s meant to be reusable and consumed by several other mta’s.

In the end the wizard will generate a UI5 project. Therefor delete the “webapp” folder and define the module as a library in the ui5.yaml file.

Now we can create a “src” folder with the content of the library. The content of the library can be generated from the Web IDE Full-Stack or a Yeoman generator:

You can also do this manually based on my example:

Make sure that the library has this structure in the end:

I’m only using an example control for demo purpose.

Build library

First attention point. You need to make sure the library contains the correct building scripts for building and deploying the library to CF. The result in the dist folder is important to be able to deploy and have access to the library from your UI5 app.

Add the following scripts to the package.json:

"scripts": {
    "build": "npm run clean && ui5 build --include-task=generateManifestBundle generateCachebusterInfo && npm run flatten && npm run clean-after-flatten && cp ./xs-app.json dist  && npm run zip",
    "zip": "cd dist && npx bestzip ../ *",
    "flatten": "cp -r dist/resources/be/wl/examplelibrary/* dist && cp dist/resources/be/wl/examplelibrary/.library dist ",
    "clean": "npx rimraf dist",
    "clean-after-flatten": "rm -rf dist/resources dist/test-resources"


This script will not only build the library but also make the folder structure flat. This was my first mistake ? I thought this was only needed when deploying to ABAP. It’s also required for deploying to CF. The deploy will look for the manifest file at the top level of the dist folder. It’s also needed to make the correct mapping for your namespace to the library.

Consume library in app

Just like you would consume any other UI5 library, add it to the list of lib in the dependencies section of sap.ui5:

Start using it in your view:

Run in BAS

Now, here comes the second attention point. Running in BAS requires a different path to the library. Compared to the Central AppRouter, BAS doesn’t use the service id in the url. You need to define a mapping in the resourceroots property of UI5 SDK bootstrap script in the index.html.

Resourceroots contains a mapping between the name of the library (including the namespace) and the path. The path will be the id of the library which is the namespace + name without the dots.

It’s important to not do this in the manifest. Otherwise it will not work in the Central Approuter. In BAS you start the app from the index.html page (which contains the resourceroots property) and in cFLP (with the Central AppRouter) it starts from the Component.js which has no resource roots property.


Next attention point, you have to copy the library into the same project as the app. Currently BAS is not able to access libraries from another mta/project. (You do not have to delete the library from the mta when you want to deploy. The library is not configured in the mta and won’t be deployed)

This also requires additional config. Go to the “run” settings of your app, right click and click on “Show in file”:

Add ,\”dist\” to “MOCK_LOOKUP_DIRS”:

When you now restart the app, it will search for all the webapp and dist folders in the current mta/project.

This should do the trick to run your app in BAS and load the library.

Run in Central AppRouter

After deploying the library to the HTML5 App Repo, you can start using them in the Fiori Launchpad.

First sync the apps in portal:

Make the tiles and test the apps, for this you can use the following blog post:

As soon as you added them as a tile to FLP, the app will run and load the library without any additional config. FLP will start the app from the component.js and so won’t use the resourceroots mapping defined in the index.html

Run in HTML5 App Repo

Until now, I’ve only tested the app in BAS and FLP using the Central Approuter. But maybe you want a stand-alone app? Or you just want to test it first in the HTML5 App Repo.

To do so, you need to change the resourceroots path in index.thml to the path that also contains the service id (without dots) in the url. The service id and library id are separated with a dotslike this:

,”be.wl.ScannerAppLibrary”: “/bewlscanner.bewlScannerAppLibrary”

I did this for my demo app of the QR Scanner app:

Keep attention that this will only work in the HTM5 App Repo and FLP but not in BAS. The solution for this is in the next topic.

You can find the apps in the HTML5 App Repo here:

In some trial accounts this menu item is not yet available. In that case you can still access the apps from the HTML5 Appr Repo with the following command:

“cf html5-list -u -d”

Run everywhere

This is an ugly workaround but if you really want to test in BAS, HTML5 App Repo and cFLP do the following.

  1. Remove resource roots from index
  2. Remove library dependency from manifest.json
  3. Add the following to the component.js
    //to make it work in app studio
    sap.ui.getCore().loadLibrary("be.wl.ScannerAppLibrary", "/bewlScannerAppLibrary/be/wl/ScannerAppLibrary");
    //to make it work in central approuter and HTML5 App Repo
    sap.ui.getCore().loadLibrary("be.wl.ScannerAppLibrary", "/bewlscannerapp.bewlScannerAppLibrary/resources/be/wl/ScannerAppLibrary");

Here you have an example:

Additional information

Use the same SAP Cloud service id for all the apps/libraries in the same mta.

Every other mta can have his own SAP Cloud service id.

Try to keep the library in a separate mta. It’s designed to be consumed by other apps which will not all be in the same mta. Do not put one app in the same mta and another app separated. Keeping the library separated allows you to do updates without having a direct relationship with other apps.



Example of app and library in separated mta’s (recommended approach):


Example of app and library in one mta:


Example of app and library that run in BAS, HTML5 App Repo and FLP (not the best solution):


Again a big thanks to Yuval Morad and his team for all the help to make this work!

You must be Logged on to comment or reply to a post.
    • Hi Wouter,

      I have cloned your project and was able to run it successfully in the CF Launchpad.

      However, if I try to consume the library from my own UI5 app, the Launchpad (or central app router?) tries to fetch the library resources from, instead of HTML5 app repo.

      What I have done is only to add dependency to manifest.json and use the library in App.view.xml (as described in your blog).


              "dependencies": {
                  "minUI5Version": "1.66.0",
                  "libs": {
                      "sap.ui.core": {},
                      "sap.m": {},
                      "sap.ui.layout": {},


      	<Shell id="shell">
      		<App id="app">
      				<Page id="page" title="{i18n>title}">
                              <x:Example text="Example app consuming library in CF"/>                    

      Do you have any idea where this difference is coming from?

      • Try cloning from the branch library-fix


        in master I removed the library reference in the manifest

        "dependencies": {
        "minUI5Version": "1.60.1",
        "libs": {
        "sap.ui.core": {},
        "sap.m": {},
        "sap.ui.layout": {},

        • Hi Wouter Lemaire and Wolfgang Röckelein,

          The reason why my app could not call the library was because it was using instance-level destination.

          Once I changed it to subaccount level destination, it started to work.

          I assume that if the library and the consuming app belong to different destination instances, library cannot be loaded.

          I'm thinking of using this Managed Approuter approach so that the library and the app are connected to the same destination instance.

  • Hi Wouter,

    I created a small dummy library but cant seem to get it to work. Can i use it in a local development enviroment as well ( vscode) and i was having some issues deploying the app. I think im laking some general knowledge as to how to deploy a library and reuse it. Do you have any ideas of recomended reading to help me along?

  • Thanks Wouter Lemaire for this blog!

    What we use to make this work in BAS and VSC without disturbing everything else is this:

    • have for development libraries and apps as directories next to each other on the same level
    • have the libraries as local relative dependencies ( file:../abc ) in the package.json of the apps
    • Use fiori tools and fiori-tools-servestatic middleware with the configuration
            - path: /resources/com
              src: "dist/resources/com/"
      where both com are the starting characters of our library ids like the be in your case

    npm install will thus the build the libraries also and will make them available in dist for the test run with fiori tools. Thus one could even make changes to app and library without comitting and test your changes, you just need to invoke npm install after any library change.

    • That’s even better, thanks for sharing! Would be even better to share an example app or make a pull request on my example 😉