SAP/ui5-tooling

Relative paths for project shims

pwasem opened this issue · 0 comments

Is your feature request related to a problem? Please describe.

Currently there is a mismatch for project shims regarding their paths when running ui5 serve and after running ui5 build.

Let's have a look at the following configuration (according to this example)

---
# Shims for thirdparty modules
specVersion: "2.3"
kind: extension
type: project-shim
metadata:
  name: thirdparty-shims
shims:
  configurations:
    # polyfill for ECMAScript features
    core-js-bundle:
      specVersion: "2.3"
      type: module
      metadata:
        name: core-js-bundle
      resources:
        configuration:
          paths:
            /resources/my/app/namespace/thirdparty/core-js-bundle/: ""
    # transpile generator functions (~ async await)
    regenerator-runtime:
      specVersion: "2.3"
      type: module
      metadata:
        name: regenerator-runtime
      resources:
        configuration:
          paths:
             /resources/my/app/namespace/thirdparty/regenerator-runtime/: ""

In particular above project shims have been defined to provide some polyfills when using e.g.

To ensure that these polyfills are being loaded as early as possible they have to be defined as js resources in the app's manifest.json:

{
  "sap.ui5": {
    "resources": {
      "css": [],
      "js": [
        {
          "uri": "/resources/my/app/namespace/thirdparty/core-js-bundle/minified.js"
        },
        {
          "uri": "/resources/my/app/namespace/thirdparty/regenerator-runtime/runtime.js"
        }
      ]
    }
  }
}

This works perfectly fine when running the app locally using ui5 serve.

The issue occurs when building the app (additionally using ui5-task-copy-shim-resource to ensure the project shims / polyfills are being copied over to the dist folder):

builder:
  resources:
    excludes:
      - "**/test/**"
      - "**/localService/**"
  customTasks:
    # babel
    - name: ui5-task-babel
      afterTask: replaceVersion
    # copy-shim-resources
    - name: ui5-task-copy-shim-resources
      afterTask: ui5-task-babel
      configuration:
        paths:
          - "/resources/my/app/namespace/thirdparty/core-js-bundle/minified.js"
          - "/resources/my/app/namespace/thirdparty/regenerator-runtime/runtime.js"

After running ui5 build the dist folder will contain a thirdparty folder, hence the paths for the js resources defined in manifest.json will not match anymore, they would have to be adjusted now omitting the /resources/my/app/namespace prefix to match the dist folder structure.

{
  "sap.ui5": {
    "resources": {
      "css": [],
      "js": [
        {
          "uri": "/thirdparty/core-js-bundle/minified.js"
        },
        {
          "uri": "/thirdparty/regenerator-runtime/runtime.js"
        }
      ]
    }
  }
}

Describe the solution you'd like

For normal project shims which are only being loaded via sap.ui.define this will not be an issue.
But for js resources such as polyfills which have to be included in manifest.json it should be possible to define their paths omitting the ´/resources/my/app/namespace` prefix so that the paths for shims are always relative to the projects webapp folder and namespace.

E.g.

---
# Shims for thirdparty modules
specVersion: "2.3"
kind: extension
type: project-shim
metadata:
  name: thirdparty-shims
shims:
  configurations:
    # polyfill for ECMAScript features
    core-js-bundle:
      specVersion: "2.3"
      type: module
      metadata:
        name: core-js-bundle
      resources:
        configuration:
          paths: # relative to webapp folder / namespace
            /thirdparty/core-js-bundle/: ""
    # transpile generator functions (~ async await)
    regenerator-runtime:
      specVersion: "2.3"
      type: module
      metadata:
        name: regenerator-runtime
      resources:
        configuration:
          paths: # relative to webapp folder / namespace
             /thirdparty/regenerator-runtime/: ""

Describe alternatives you've considered

It would be possible to do some conditional sap.ui.loader.config and sap.ui.requireSync at the start of Component.js instead of manifest.json:sap.ui5/resources/js but that is something I would rather avoid.

Additional context

The full ui5.yaml would look like this:

specVersion: "2.3"
metadata:
  name: my-app
type: application
framework:
  name: SAPUI5
  version: "1.84.4"
  libraries:
    - name: sap.m
    - name: sap.ui.core
    - name: sap.suite.ui.generic.template
    - name: themelib_sap_fiori_3
      optional: true
    - name: sap.ushell
      development: true
    - name: sap.ui.fl
      development: true
server:
  customMiddleware:
  # livereload
  - name: fiori-tools-appreload
    afterMiddleware: compression
    configuration:
      ext: html,js,json,xml,properties,change
  # service proxy
  - name: ui5-middleware-http-proxy
    mountPath: /sap
    afterMiddleware: compression
    configuration:
      baseUrl: https://my.abap.system:44311
      path: /sap
      secure: false
      auth:
        user: env:ABAP_SYSTEM_USERNAME
        pass: env:ABAP_SYSTEM_PASSWORD
  # layered respository / flexibility
  - name: ui5-middleware-lrep-flex
    afterMiddleware: compression
    configuration:
      # handle e.g. GET /sap/bc/lrep/flex/data/bookshop.ui.Component?appVersion=1.0.0&sap-language=en
      component:
        # data to be merged to each .change file
        changeData:
          support:
            user: "SAP"
          validAppVersions:
            creation: "0.1.0"
            from: "0.1.0"
            to: "0.1.0"
        # data to be merged and sent for each response
        data:
          settings:
            isKeyUser: true
            isAtoAvailable: false
            isProductiveSystem: false
   # babel
  - name: ui5-middleware-babel
    afterMiddleware: compression
    configuration:
      enabled: true
      wrap: true
      excludes:
        - "/test/**"
        - "/localService/**"
        - "/resources/my/app/namespace/thirdparty/core-js-bundle/**"
        - "/resources/my/app/namespace/thirdparty/regenerator-runtime/**"
builder:
  componentPreload:
  excludes:
    - "**/thirdparty/core-js-bundle/**"
    - "**/thirdparty/regenerator-runtime/**"
  resources:
    excludes:
      - "**/test/**"
      - "**/localService/**"
  customTasks:
    # babel
    - name: ui5-task-babel
      afterTask: replaceVersion
    # copy-shim-resources
    - name: ui5-task-copy-shim-resources
      afterTask: ui5-task-babel
      configuration:
        paths:
          - "/resources/my/app/namespace/thirdparty/core-js-bundle/minified.js"
          - "/resources/my/app/namespace/thirdparty/regenerator-runtime/runtime.js"
---
# Shims for thirdparty modules
specVersion: "2.3"
kind: extension
type: project-shim
metadata:
  name: thirdparty-shims
shims:
  configurations:
    # polyfill for ECMAScript features
    core-js-bundle:
      specVersion: "2.3"
      type: module
      metadata:
        name: core-js-bundle
      resources:
        configuration:
          paths:
            /resources/my/app/namespace/thirdparty/core-js-bundle/: ""
    # transpile generator functions (~ async await)
    regenerator-runtime:
      specVersion: "2.3"
      type: module
      metadata:
        name: regenerator-runtime
      resources:
        configuration:
          paths:
            /resources/my/app/namespace/thirdparty/regenerator-runtime/: ""