Search code examples
npmsapui5ui5-tooling

How to build a multi component application?


I have an OpenUI5 project with the structure depicted below. It contains one RootComponent that displays two other separate Components (UserComponent and AdminComponent).

my-app/
├─ node_modules/
├─ RootComponent/
│  ├─ package.json
│  ├─ ui5.yaml
│  ├─ webapp/
│  |  ├─ manifest.json
│  |  ├─ Component.js
├─ UserComponent/
│  ├─ package.json
│  ├─ ui5.yaml
│  ├─ webapp/
│  |  ├─ manifest.json
│  |  ├─ Component.js
├─ AdminComponent/
│  ├─ package.json
│  ├─ ui5.yaml
│  ├─ webapp/
│  |  ├─ manifest.json
│  |  ├─ Component.js
├─ package.json
├─ README.md

However, when I run npm install and then build the RootComponent project using the UI5 CLI, the UserComponent and AdminComponent are not included in the build output. The console prints the error:

**** error: missing module my/app/user/Component.js

I am following the example provided in an official sample repository. When I locally build this sample project using ui5 build --all, the dependent components are built into the resources folder of the output directory, as depicted here.


Folder Structure with dependent Components


When I execute the same command in my own RootComponent project, the resulting resources folder contains the dependencies from the sap.* packages, but not the UserComponent and the AdminComponent. Thus, when I run the RootComponent on a web server, I am getting 404 errors.

My truncated configuration files are listed below:

RootComponent/package.json

{
    "name": "my-app-root",
    "version": "1.0.0",
    "scripts": {
        "build": "ui5 build self-contained --all --dest=../../webapp --clean-dest",
        // ...
    },
    "dependencies": {
        "my-app-user": "file:../UserComponent",
        "my-app-admin": "file:../AdminComponent"
    },
    "devDependencies": {
        // ...
    }
}

RootComponent/ui5.yaml

specVersion: "3.0"
metadata:
  name: my.app.root
type: application
builder:
  customTasks:
  - name: ui5-tooling-modules-task
    afterTask: replaceVersion
server:
  customMiddleware:
    - name: ui5-middleware-livereload
      afterMiddleware: compression
framework:
  name: OpenUI5
  version: "1.118.0"

RootComponent/webapp/manifest.json

{
    "_version": "1.12.0",
    "sap.app": {
        "id": "my.app.root",
        "type": "application",
        "i18n": "i18n/i18n.properties",
        "title": "{{appTitle}}",
        "description": "{{appDescription}}",
        "applicationVersion": {
            "version": "1.0.0"
        }
    },
    "sap.ui": {
        // ...
    },
    "sap.ui5": {
        "rootView": {
            // ...
        },
        "componentUsages": {
            "UserComponent": {
                "name": "my.app.user",
                "settings": {},
                "componentData": {},
                "lazy": true
            },
            "AdminComponent": {
                "name": "my.user.admin",
                "settings": {},
                "componentData": {},
                "lazy": true
            }
        },
        "dependencies": {
            "minUI5Version": "1.118.0",
            "libs": {
                "sap.ui.core": {},
                "sap.m": {}
            },
            "components": {
                "my.app.user": {},
                "my.app.admin": {}
            }
        },
        "models": {
            "i18n": {
                // ...
            }
        },
        "routing": {
            "config": {
                // ...
            },
            "routes": [
                // ...
            ],
            "targets": {
                "user": {
                    "type": "Component",
                    "usage": "UserComponent"
                },
                "admin": {
                    "type": "Component",
                    "usage": "AdminComponent"
                }
            }
        }
    }
}

UserComponent/package.json

{
    "name": "pars-web-user",
    "version": "1.0.0",
    "scripts": {
        "build": "ui5 build --clean-dest --all"
        // ...
    },
    "dependencies": {
        // ...
    },
    "devDependencies": {
        // ...
    }
}

UserComponent/webapp/manifest.json

{
    "_version": "1.12.0",

    "sap.app": {
        "id": "my.app.user",
        "type": "application",
        "i18n": "i18n/i18n.properties",
        "title": "{{appTitle}}",
        "description": "{{appDescription}}",
        "applicationVersion": {
            "version": "1.0.0"
        }
    },
    // ...
}

What do I need in order to successfully include the two dependent Components into the build output? What piece am I missing?


Solution

  • I resolved my problem. The issue was that the ui5.yaml files of the UserComponent and AdminComponent contained the attribute

    type: application
    

    But this attribute should only be set at the RootComponent. The child components should contain the attribute

    type: library
    

    instead.
    After renaming the root folders of UserComponent and AdminComponent from webapp into src, the build finally worked and the Components were added to the resources folder.