We have a SAPUI5 app in where we define multiple components (i.e., multiple Component.js files) each in a respective subfolder as direct child of the application root. The following image shows the project structure:
Component 1 is specified as com.test.component1
, component 2 as com.test.component2
. Shared code is located in root/shared
and defined as dependencies in the controllers of each component.
shared/Utils.js:
sap.ui.define([], function () {
"use strict";
return {...};
};
component1/controller/Controller1.js:
sap.ui.define([
"sap/ui/core/mvc/Controller",
"test/shared/Utils"
], function (BaseController, Utils) {
"use strict";
// controller code
});
Running the index.html file locally (or in WebIDE) this all works, but the shared resources are not found when we try to integrate the different components into the Fiori Launchpad (it tries to load them from /resources/shared). We believe this has sth to do with the data-sap-ui-resourceroots='{"com.test": ""}
defined for bootstrapping which is missing either in the Component.js or the manifest.json file.
What's the right way to register the resource path com/test/shared
for the individual components?
One way to solve this is by defining the resourceRoots
attribute in the application descriptor (manifest.json):
{
...
"sap.ui5": {
...
"resourceRoots" : {
"com.test.shared": "./../shared"
},
...
}
}
This works despite what's written in the documentation:
Map of URL locations keyed by a resource name prefix; only relative paths inside the component are allowed and no ".." characters
Using a Component/library for your utilities
The most obvious question I have here is: If you use the component concept anyways why is your shared code not a component as well. A Component does not necessarily have to have a UI, that's why there is a UIComponent
and a simple Component
to inherit from. You just load it as a dependency of component1/component2 like this:
...
return Component.extend("com.test.Component1", {
metadata: {
name: "Component1",
dependencies: {
libs: [ "sap.m" ],
components: [ "test.shared" ]
},
...
If using a Component does not feel right for you, you could also package your utilities as a library. You might want to check out grunt-openui5 that helps you building one.
Loading external files without using Component/library concept
Anyways defining a resourceroot on bootstrap is similar to a call to
jQuery.sap.registerModulePath("test.shared", "/path/to/your/source");
You could register the module path of your shared modules in both of the components init. You will probably have to use an absolute path there since depending on the execution context (launchpad vs. standalone) the relative path might differ.
You could make the path 'relative' like this:
jQuery.sap.registerModulePath("test.shared", jQuery.sap.getModulePath("com.test.Component1") +"/../shared);
Furhtermore if you want the shared resources to also benefit from cache busting you might want to use this afterwards:
sap.ui.core.AppCacheBuster.register(jQuery.sap.getModulePath("test.shared"));