Content Navigation
Part 1: A simple UI5 app that runs in the SAP Build Work Zone Service
Part 2: Multiple Apps with a Shared Reuse Library (Current post)
Part 3: Splitting bigger projects (Planned)
Multiple Apps with a Shared Reuse Library
In part 1 you have learned how to build and deploy a single app. In this 2nd part this is now extended to multiple apps that share a reuse library with common code.
The library contains a control as well as a reuse component.
The sample code can be found in the GitHub repository.
Deployed Content
Let’s have a look at how the deployment looks now and what has changed. The needed service instances haven’t changed at all, but more HTML5 apps are now deployed to the same app host:
Both apps depend on the reuse library, which is expressed in their manifest.json file under sap.ui5/dependencies. The reuse library contains an embedded manifest.json for the component.
MTA Project Structure
The mta.yaml of the project has been enhanced slightly. Two more modules for the 2nd app and the library are added and they are required by the UI deployer module:
The UI5 Library
The library contains only the bare minimum to demonstrate relevant aspects. Here it contains a sample reusable control and an embedded reusable component. Of course there could also be other reusable content like base classes, etc.
Build
The UI5 library uses UI5 Tooling for its build process. You control the build the same way as you do for apps, using the package.json and the ui5-deploy.yaml files.
In the ui5-deploy.yaml and the manifest.json the type is now set to library.
For libraries, the builder requires a different project structure. Instead of a webapp folder there must be a src folder.
Since version 3.0 of the UI5 Tooling, it is no longer needed to add a folder structure for the library namespace.
Instead of a Component.js file the library contains the files library.js and .library to define the library metadata.
The build produces a library-preload.js file that packages all minified files including the sources of the reuse component. No dedicated Component-preload.js is produced.
Routings
The xs-app.json file only contains a route to serve its own sources.
This lib does not use its own OData service, but this would be possible for the embedded component. In that case you would have to create a corresponding route here.
{
“authenticationMethod”: “route”,
“routes”: [
{
“source”: “^(.*)$”,
“target”: “$1”,
“service”: “html5-apps-repo-rt”,
“authenticationType”: “xsuaa”
}
]
}
The lib doesn’t need to be started standalone and therefore has no ui5.yaml with a local middleware.
Note that if you want to build unit test pages for the library you might need a local test environment for it, just like for the apps.
App Descriptor
The lib has a manifest.json file that defines a unique sap.app/id and the sap.app/type library for it. There are no inbounds and no services defined, but the embeds property lists the subfolder of the embedded reuse component
“sap.app”: {
“id”: “btp.samples.cdm.multiple.apps.lib”,
“type”: “library”,
“i18n”: “i18n/i18n.properties”,
“title”: “{{title}}”,
“applicationVersion”: {
“version”: “1.0.0”
},
“embeds”:[“comp/reuse”]
}
It also specifies sap.cloud/service with the same service name as for the apps. All content which is deployed to one app-host must be aligned and have the same value here.
“sap.cloud”: {
“public”: true,
“service”: “btp.samples.cdm.multiple.apps”
}
The Embedded Component
The component is located in the comp/reuse subfolder. It is kept simple and only contains a Main view that renders a simple button in the Main.view.xml file. It does not declare any models or use any OData services, but this would be possible in the same way as for an application.
The manifest.json defines type as component and an ID which is constructed including the parent library ID and the relative path inside. This is needed to avoid any issues with module path resolution.
It declares the embeddedBy property with the path to the embedding library. This is an important indicator for the platform that the preload package of the component is part of the library preload package. Without it, there might be an unnecessary request at startup which ends with a 404 Not Found error.
{
“_version”: “1.60.0”,
“sap.app”: {
“id”: “btp.samples.cdm.multiple.apps.lib.comp.reuse”,
“type”: “component”,
“i18n”: “i18n/i18n.properties”,
“title”: “{{appTitle}}”,
“description”: “{{appDescription}}”,
“applicationVersion”: {
“version”: “1.0.0”
},
“embeddedBy”: “../../”
}
}
There is no need to specify the sap.cloud node here. This will be inherited from the manifest.json of the lib.
The UI5 Apps
For the apps (app1 and app2) there are only minor changes.
In the manifest.json of both apps the dependency to the library has been added.
Additionally there is a component usage for the reuse component.
“sap.ui5”: {
“dependencies”: {
“minUI5Version”: “1.95.0”,
“libs”: {
“sap.ui.core”: {},
“sap.m”: {},
“sap.f”: {},
“btp.samples.cdm.multiple.apps.lib”: {}
}
},
“componentUsages”: {
“reuse”: {
“name”: “btp.samples.cdm.multiple.apps.lib.comp.reuse”,
“settings”: {},
“componentData”: {},
“lazy”: false
}
}
}
There are no resourceRoots URLs defined here because these depend on the way the apps are started.
The Master.view.xml uses the library by adding the reuse control.
Additionally, there is a component container that shows the component usage.
<mvc:View
controllerName=”btp.samples.cdm.multiple.apps.app1.controller.Master”
xmlns=”sap.m”
xmlns:core=”sap.ui.core”
xmlns:semantic=”sap.f.semantic”
xmlns:mvc=”sap.ui.core.mvc”
xmlns:lib=”btp.samples.cdm.multiple.apps.lib”>
<!– Reuse control from shared lib –>
<lib:controls.Reuse text=”App1″ />
<core:ComponentContainer usage=”reuse” manifest=”true” async=”true” />
</mvc:View>
Routings
The xs-app.json files of the apps have not changed. There is no route for the library added because the library will be accessed directly and not via the apps.
However the ui5.yaml files that define the server for the local run have been enhanced.
They define the entire isolated test environment for an app and therefore also need a route mapping for the static sources of the lib.
The lib is mounted under a subfolder which has the pattern <Service Name (without dots)>.<sap.app/id (without dots)>. The reason the path is named this way will be explained later.
server:
customMiddleware:
– name: fiori-tools-servestatic
afterMiddleware: compression
configuration:
paths:
– path: /btpsamplescdmmultipleapps.btpsamplescdmmultipleappslib
src: “../lib/src”
Resource Mappings
The index.html needs to define a resource mapping for the library to tell UI5 where to find the resources. It maps the library name to the subfolder defined in the custom middleware.
<script id=”sap-ui-bootstrap”
src=”https://ui5.sap.com/resources/sap-ui-cachebuster/sap-ui-core.js”
data-sap-ui-theme=”sap_fiori_3″
data-sap-ui-resourceroots='{
“btp.samples.cdm.multiple.apps.app1”: “./”,
“btp.samples.cdm.multiple.apps.lib”: “./btpsamplescdmmultipleapps.btpsamplescdmmultipleappslib”
}’
data-sap-ui-libraries=”sap.m”
data-sap-ui-oninit=”module:sap/ui/core/ComponentSupport”
data-sap-ui-compatVersion=”edge”
data-sap-ui-async=”true”
data-sap-ui-preload=”async”
data-sap-ui-frameOptions=”trusted”>
</script>
Running locally
Again, to start the local test just run the start or start-local script in one of the package.json files.
The UI5 runtime will be able to load the library using the mapped paths which will be resolved by the local middleware and served from the source folder of the library.
Running the Deployed Apps
Deploying the App
Build and deploy the single MTA project in the same way as before.
Running Standalone
After the deployment, the apps can be run standalone from their index.html via the managed approuter. You can find them in the SAP BTP cockpit on the HTML5 Applications page under your subaccount.
Since the same index.html page is used, the same resource mapping for the library will be used, which loads the resources from a sub path with the name <Service Name (without dots)>.<sap.app/id (without dots)>. This makes use of a special feature of the managed approuter, which allows to address dependencies to other HTML5 applications with a relative path. For running locally, the same path has been chosen to configure the custom middleware. This simulates the behavior of the managed approuter and allows you to use the same path and reuse of the index.html.
Formerly this relative path resolution was not supported, and this path could not be hardcoded. Instead, it required a script in the index.html to calculate it. This has been simplified now.
Running in the SAP Build Work Zone Service
To run the in the Launchpad configure it as content provider as described in Part 1 – Running in the SAP Build Work Zone Service. Afterwards you can run the new apps in the same way as before.
Here the platform will provide the URLs to access the apps and the library.
If you check the ui5AppInfo.json that is used to start the app you can find the additional dependencies for the library. The reuse component doesn’t appear here, because it is embedded in the library and all paths can be derived from it.
Note that here the paths for the library are not relative to the consuming app but are directly below the root. Both paths are possible and access the same content. It depends on the use case which way is more convenient to use.
{
“name”: “btp.samples.cdm.multiple.apps.app1”,
“url”: “/461b5f6c-c16b-4344-bb67-cd5bd3acd019.btpsamplescdmmultipleapps.btpsamplescdmmultipleappsapp1/~a48cdea1-913e-451f-9dee-146e2897b567~/”,
“manifest”: true,
“asyncHints”: {
“libs”: [
{
“name”: “sap.m”,
“lazy”: false
},
{
“name”: “sap.f”,
“lazy”: false
},
{
“name”: “btp.samples.cdm.multiple.apps.lib”,
“url”: {
“url”: “/461b5f6c-c16b-4344-bb67-cd5bd3acd019.btpsamplescdmmultipleapps.btpsamplescdmmultipleappslib/~a48cdea1-913e-451f-9dee-146e2897b567~/”,
“final”: true
},
“lazy”: false
},
{
“name”: “sap.ui.fl”,
“lazy”: false
}
],
“components”: []
},
“messages”: [],
“version”: “1.0.0”
}
Next Steps
>You are now ready to build multiple apps and move their common parts into a reusable library.
However, everything is still contained in the same MTA project. In bigger projects, you might need to split this into smaller parts in order to achieve independent lifecycles and split responsibilities.
Watch out for Part 3 of this blog which will be published soon.
Content NavigationPart 1: A simple UI5 app that runs in the SAP Build Work Zone ServicePart 2: Multiple Apps with a Shared Reuse Library (Current post)Part 3: Splitting bigger projects (Planned) Multiple Apps with a Shared Reuse LibraryIn part 1 you have learned how to build and deploy a single app. In this 2nd part this is now extended to multiple apps that share a reuse library with common code.The library contains a control as well as a reuse component.The sample code can be found in the GitHub repository.Deployed ContentLet’s have a look at how the deployment looks now and what has changed. The needed service instances haven’t changed at all, but more HTML5 apps are now deployed to the same app host:Both apps depend on the reuse library, which is expressed in their manifest.json file under sap.ui5/dependencies. The reuse library contains an embedded manifest.json for the component.MTA Project StructureThe mta.yaml of the project has been enhanced slightly. Two more modules for the 2nd app and the library are added and they are required by the UI deployer module:The UI5 LibraryThe library contains only the bare minimum to demonstrate relevant aspects. Here it contains a sample reusable control and an embedded reusable component. Of course there could also be other reusable content like base classes, etc.BuildThe UI5 library uses UI5 Tooling for its build process. You control the build the same way as you do for apps, using the package.json and the ui5-deploy.yaml files.In the ui5-deploy.yaml and the manifest.json the type is now set to library.For libraries, the builder requires a different project structure. Instead of a webapp folder there must be a src folder.Since version 3.0 of the UI5 Tooling, it is no longer needed to add a folder structure for the library namespace.Instead of a Component.js file the library contains the files library.js and .library to define the library metadata.The build produces a library-preload.js file that packages all minified files including the sources of the reuse component. No dedicated Component-preload.js is produced.RoutingsThe xs-app.json file only contains a route to serve its own sources.This lib does not use its own OData service, but this would be possible for the embedded component. In that case you would have to create a corresponding route here.{
“authenticationMethod”: “route”,
“routes”: [
{
“source”: “^(.*)$”,
“target”: “$1”,
“service”: “html5-apps-repo-rt”,
“authenticationType”: “xsuaa”
}
]
}The lib doesn’t need to be started standalone and therefore has no ui5.yaml with a local middleware.Note that if you want to build unit test pages for the library you might need a local test environment for it, just like for the apps.App DescriptorThe lib has a manifest.json file that defines a unique sap.app/id and the sap.app/type library for it. There are no inbounds and no services defined, but the embeds property lists the subfolder of the embedded reuse component”sap.app”: {
“id”: “btp.samples.cdm.multiple.apps.lib”,
“type”: “library”,
“i18n”: “i18n/i18n.properties”,
“title”: “{{title}}”,
“applicationVersion”: {
“version”: “1.0.0”
},
“embeds”:[“comp/reuse”]
}It also specifies sap.cloud/service with the same service name as for the apps. All content which is deployed to one app-host must be aligned and have the same value here.”sap.cloud”: {
“public”: true,
“service”: “btp.samples.cdm.multiple.apps”
}The Embedded ComponentThe component is located in the comp/reuse subfolder. It is kept simple and only contains a Main view that renders a simple button in the Main.view.xml file. It does not declare any models or use any OData services, but this would be possible in the same way as for an application.The manifest.json defines type as component and an ID which is constructed including the parent library ID and the relative path inside. This is needed to avoid any issues with module path resolution.It declares the embeddedBy property with the path to the embedding library. This is an important indicator for the platform that the preload package of the component is part of the library preload package. Without it, there might be an unnecessary request at startup which ends with a 404 Not Found error.{
“_version”: “1.60.0”,
“sap.app”: {
“id”: “btp.samples.cdm.multiple.apps.lib.comp.reuse”,
“type”: “component”,
“i18n”: “i18n/i18n.properties”,
“title”: “{{appTitle}}”,
“description”: “{{appDescription}}”,
“applicationVersion”: {
“version”: “1.0.0”
},
“embeddedBy”: “../../”
}
}There is no need to specify the sap.cloud node here. This will be inherited from the manifest.json of the lib.The UI5 AppsFor the apps (app1 and app2) there are only minor changes.In the manifest.json of both apps the dependency to the library has been added.Additionally there is a component usage for the reuse component.”sap.ui5″: {
“dependencies”: {
“minUI5Version”: “1.95.0”,
“libs”: {
“sap.ui.core”: {},
“sap.m”: {},
“sap.f”: {},
“btp.samples.cdm.multiple.apps.lib”: {}
}
},
“componentUsages”: {
“reuse”: {
“name”: “btp.samples.cdm.multiple.apps.lib.comp.reuse”,
“settings”: {},
“componentData”: {},
“lazy”: false
}
}
}There are no resourceRoots URLs defined here because these depend on the way the apps are started.The Master.view.xml uses the library by adding the reuse control.Additionally, there is a component container that shows the component usage.<mvc:View
controllerName=”btp.samples.cdm.multiple.apps.app1.controller.Master”
xmlns=”sap.m”
xmlns:core=”sap.ui.core”
xmlns:semantic=”sap.f.semantic”
xmlns:mvc=”sap.ui.core.mvc”
xmlns:lib=”btp.samples.cdm.multiple.apps.lib”>
<!– Reuse control from shared lib –>
<lib:controls.Reuse text=”App1″ />
<core:ComponentContainer usage=”reuse” manifest=”true” async=”true” />
</mvc:View>RoutingsThe xs-app.json files of the apps have not changed. There is no route for the library added because the library will be accessed directly and not via the apps.However the ui5.yaml files that define the server for the local run have been enhanced.They define the entire isolated test environment for an app and therefore also need a route mapping for the static sources of the lib.The lib is mounted under a subfolder which has the pattern <Service Name (without dots)>.<sap.app/id (without dots)>. The reason the path is named this way will be explained later.server:
customMiddleware:
– name: fiori-tools-servestatic
afterMiddleware: compression
configuration:
paths:
– path: /btpsamplescdmmultipleapps.btpsamplescdmmultipleappslib
src: “../lib/src”Resource MappingsThe index.html needs to define a resource mapping for the library to tell UI5 where to find the resources. It maps the library name to the subfolder defined in the custom middleware.<script id=”sap-ui-bootstrap”
src=”https://ui5.sap.com/resources/sap-ui-cachebuster/sap-ui-core.js”
data-sap-ui-theme=”sap_fiori_3″
data-sap-ui-resourceroots='{
“btp.samples.cdm.multiple.apps.app1”: “./”,
“btp.samples.cdm.multiple.apps.lib”: “./btpsamplescdmmultipleapps.btpsamplescdmmultipleappslib”
}’
data-sap-ui-libraries=”sap.m”
data-sap-ui-oninit=”module:sap/ui/core/ComponentSupport”
data-sap-ui-compatVersion=”edge”
data-sap-ui-async=”true”
data-sap-ui-preload=”async”
data-sap-ui-frameOptions=”trusted”>
</script>Running locallyAgain, to start the local test just run the start or start-local script in one of the package.json files.The UI5 runtime will be able to load the library using the mapped paths which will be resolved by the local middleware and served from the source folder of the library. Running the Deployed AppsDeploying the AppBuild and deploy the single MTA project in the same way as before.Running StandaloneAfter the deployment, the apps can be run standalone from their index.html via the managed approuter. You can find them in the SAP BTP cockpit on the HTML5 Applications page under your subaccount.Since the same index.html page is used, the same resource mapping for the library will be used, which loads the resources from a sub path with the name <Service Name (without dots)>.<sap.app/id (without dots)>. This makes use of a special feature of the managed approuter, which allows to address dependencies to other HTML5 applications with a relative path. For running locally, the same path has been chosen to configure the custom middleware. This simulates the behavior of the managed approuter and allows you to use the same path and reuse of the index.html.Formerly this relative path resolution was not supported, and this path could not be hardcoded. Instead, it required a script in the index.html to calculate it. This has been simplified now.Running in the SAP Build Work Zone ServiceTo run the in the Launchpad configure it as content provider as described in Part 1 – Running in the SAP Build Work Zone Service. Afterwards you can run the new apps in the same way as before.Here the platform will provide the URLs to access the apps and the library.If you check the ui5AppInfo.json that is used to start the app you can find the additional dependencies for the library. The reuse component doesn’t appear here, because it is embedded in the library and all paths can be derived from it.Note that here the paths for the library are not relative to the consuming app but are directly below the root. Both paths are possible and access the same content. It depends on the use case which way is more convenient to use.{
“name”: “btp.samples.cdm.multiple.apps.app1”,
“url”: “/461b5f6c-c16b-4344-bb67-cd5bd3acd019.btpsamplescdmmultipleapps.btpsamplescdmmultipleappsapp1/~a48cdea1-913e-451f-9dee-146e2897b567~/”,
“manifest”: true,
“asyncHints”: {
“libs”: [
{
“name”: “sap.m”,
“lazy”: false
},
{
“name”: “sap.f”,
“lazy”: false
},
{
“name”: “btp.samples.cdm.multiple.apps.lib”,
“url”: {
“url”: “/461b5f6c-c16b-4344-bb67-cd5bd3acd019.btpsamplescdmmultipleapps.btpsamplescdmmultipleappslib/~a48cdea1-913e-451f-9dee-146e2897b567~/”,
“final”: true
},
“lazy”: false
},
{
“name”: “sap.ui.fl”,
“lazy”: false
}
],
“components”: []
},
“messages”: [],
“version”: “1.0.0”
}Next Steps>You are now ready to build multiple apps and move their common parts into a reusable library.However, everything is still contained in the same MTA project. In bigger projects, you might need to split this into smaller parts in order to achieve independent lifecycles and split responsibilities.Watch out for Part 3 of this blog which will be published soon. Read More Technology Blogs by SAP articles
#SAP
#SAPTechnologyblog