Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem with importing third party app when UI5 is loaded through CDN. #915

Open
icostaykov opened this issue Nov 9, 2023 · 19 comments · Fixed by #922 or #929
Open

Problem with importing third party app when UI5 is loaded through CDN. #915

icostaykov opened this issue Nov 9, 2023 · 19 comments · Fixed by #922 or #929
Labels
enhancement New feature or request

Comments

@icostaykov
Copy link

Describe the bug
When loading UI5 through the cdn and trying to import a third party library, following the tutorial, the third library cannot be imported. My current issue is with jsPdf, but I have faced it with another library as well. The error I get is the following:
'jspdf-16b990c3.js': failed to load 'jspdf-16b990c3.js' from https://sapui5.hana.ondemand.com/1.117.0/resources/jspdf-16b990c3.js...

What seems to circumvent the issue of the missing file is adding to the resourceRoots not only 'jspdf': 'resources/jspdf', but also 'jspdf-16b990c3': 'resources/jspdf-16b990c3'. However, this seems like an unreliable way to solve the issue. I am not sure how this hash at the end is being generated and cannot rely on it being the same when deployed to production.

It is important to note, that there are no issues when loading UI5 locally, instead of through the CDN.

To Reproduce
Steps to reproduce the behavior:

  1. Load UI5 through CDN - in index.html, in the script tag for loading UI5, set the src to "https://sapui5.hana.ondemand.com//resources/sap-ui-core.js"
  2. Install jspdf - either npm i jspdf or yarn add jspdf
  3. Either in the index.html resourceRoots, or in the manifest.json->sap.ui5->resourceRoots, add `"jspdf": "resources/jspdf"
  4. Run npm start or yarn run start
  5. See error

Expected behavior
The app should import 3rd-party libraries without any issues, regardless of UI5 being loaded through the cdn or locally.

Desktop (please complete the following information):

  • OS: Windows 11, observed also on macOS
  • Browser Chrome
  • Version 119
@petermuessig
Copy link
Member

Hi @icostaykov ,

Please check the configuration options prependPathMappings which prepends the path mapping to the Component.js file or even better use the addToNamespace option which includes the thirdparty resources into the namespace of your application or library and rewrites the imports in the UI5 AMD-like modules and the XMLView.

Both options will fix your issue. You can also take a look into the README.md of the ui5-tooling-modules which describes these options: https://github.com/ui5-community/ui5-ecosystem-showcase/tree/main/packages/ui5-tooling-modules#configuration-options-in-yourappui5yaml

Best regards,
Peter

@petermuessig
Copy link
Member

In the tutorial you linked, the addToNamespace option is also put there in step 4.1:
https://github.com/SAP-samples/ui5-typescript-tutorial/tree/main/exercises/ex4#exercise-41---installconfigure-ui5-tooling-extensions

Did you miss to set it correctly?

@icostaykov
Copy link
Author

First, I would like to thank you for the really quick reply!

Unfortunately, I have followed the underlined part of the tutorial carefully. I had added both prependPathMappings and addToNamespace. I tried adding them separately and combined and I still get the same error. Maybe there is something else I am doing wrong?

@petermuessig
Copy link
Member

Maybe you can attach your project to allow me to look into it?

@icostaykov
Copy link
Author

Yes, @petermuessig, here is the repo I created to illustrate the issue.

@petermuessig
Copy link
Member

@icostaykov

Thanks for sharing your repository - now it is clear to me what's going wrong in your case.

In your index.html you are using UI5 from CDN. In this case you need to instruct the UI5 module loader to load the jspdf dependencies from the local resources path so that the ui5-tooling-modules can generate these dependencies. I did so by configuring the following resourceroots:

		<script
			id="sap-ui-bootstrap"
			src="https://sdk.openui5.org/1.117.0/resources/sap-ui-core.js"
			data-sap-ui-resourceroots='{
				"com.myorg.myapp": "./",
				"jspdf": "./resources/jspdf",
				"jspdf-6b40b9e7": "resources/jspdf-6b40b9e7"
			}'

Both jspdf and the chunk jspdf-??? need to be listed here. The hash of the jspdf chunk may need to be updated once a newer version is being used.

The other option is that you consume OpenUI5 via the local development server from resources/sap-ui-core.js. Then the jspdf dependencies are loaded automatically from resource/jspdf*.

HTH and BR, Peter

@petermuessig
Copy link
Member

petermuessig commented Dec 10, 2023

One thing to add: I just solved the issue in your project but not recognizing your initial issue statement again now and your ask is different. Unfortunately, when loading UI5 via CDN, there is no real possibility to configure the resourceroots before the application is loaded - except what I do when using the prependPathMappings option - but this is only usable for the task so far. Changing the usage also for the middleware requires a rework of how ui5-tooling-modules works - maybe an x-mas project (unfortunately, that's just one of my topics on my list :cry).

Maybe one short term solution would be to put all chunks into a nested folder. I'll try that. Re-opening the issue for now, as I don't know how much time I'll have before x-mas...

@petermuessig petermuessig reopened this Dec 10, 2023
petermuessig added a commit that referenced this issue Dec 10, 2023
To simplify the handling of chunks of npm packages, they are now stored
in a folder with the name of the module. With this option a single
`resourceroots` mapping is sufficient to delegate all requests to the
npm package and its chunks to the proper location. This is especially
useful for CDN scenarios when the npm package is not included.

Example: CDN usage + `jspdf`

```html
<html>
  <head>
    [...]
    <script ...
      data-sap-ui-resourceroots='{
        ...
        "jspdf": "resources/jspdf"
      }'
```

Using this `resourceroots` mapping, all requests to `jspdf` and its
chunks are now resolved to `resources/jspdf*`.

* `jspdf` => `resources/jspdf.js`
* `jspdf/0c1H2u3N4k5` => `resources/jspdf/0c1H2u3N4k5.js`

Fixes #915
petermuessig added a commit that referenced this issue Dec 10, 2023
To simplify the handling of chunks of npm packages, they are now stored
in a folder with the name of the module. With this option a single
`resourceroots` mapping is sufficient to delegate all requests to the
npm package and its chunks to the proper location. This is especially
useful for CDN scenarios when the npm package is not included.

Example: CDN usage + `jspdf`

```html
<html>
  <head>
    [...]
    <script ...
      data-sap-ui-resourceroots='{
        ...
        "jspdf": "resources/jspdf"
      }'
```

Using this `resourceroots` mapping, all requests to `jspdf` and its
chunks are now resolved to `resources/jspdf*`.

* `jspdf` => `resources/jspdf.js`
* `jspdf/0c1H2u3N4k5` => `resources/jspdf/0c1H2u3N4k5.js`

Fixes #915
@icostaykov
Copy link
Author

Thanks a lot for taking so much of your time to help out!

I have an additional question that might eather make the situation better by hinting at an easy solution, or make it worse by complicating everything - importing other 3rd party libraries in some cases works without any hassle - e.g. the html2canvas library - I just have to add "html2canvas": "resources/html2canvas" without a separate entry with the hashed chunk and I am very confused why that happens.

I added it to the same repo to show what I mean.

@jonaszuberbuehler
Copy link

@petermuessig I've just updated from 3.2.4 to 3.2.5 and in my project "xlsx-js-style": "1.2.0" does not load correctly anymore. Anything we need to adapt?

@petermuessig petermuessig reopened this Dec 24, 2023
petermuessig added a commit that referenced this issue Dec 25, 2023
The packaging of npm packages resolves the browser modules also from
the exports section of the package.json. This provides a better
coverage to detect the browser modules inside the npm packages.

In addition, this fix also allows to add polyfill overrides in the
current working directory.

Fixes #927
Fixes #915
petermuessig added a commit that referenced this issue Dec 25, 2023
The packaging of npm packages resolves the browser modules also from
the exports section of the package.json. This provides a better
coverage to detect the browser modules inside the npm packages.

In addition, this fix also allows to add polyfill overrides in the
current working directory.

Fixes #927
Fixes #915
petermuessig added a commit that referenced this issue Dec 25, 2023
The packaging of npm packages resolves the browser modules also from
the exports section of the package.json. This provides a better
coverage to detect the browser modules inside the npm packages.

In addition, this fix also allows to add polyfill overrides in the
current working directory.

Fixes #927
Fixes #915
petermuessig added a commit that referenced this issue Dec 25, 2023
The packaging of npm packages resolves the browser modules also from
the exports section of the package.json. This provides a better
coverage to detect the browser modules inside the npm packages.

In addition, this fix also allows to add polyfill overrides in the
current working directory.

Fixes #927
Fixes #915
petermuessig added a commit that referenced this issue Dec 25, 2023
The packaging of npm packages resolves the browser modules also from
the exports section of the package.json. This provides a better
coverage to detect the browser modules inside the npm packages.

In addition, this fix also allows to add polyfill overrides in the
current working directory.

Fixes #927
Fixes #915
@petermuessig
Copy link
Member

ui5-tooling-modules version 3.2.6 should fix the issue!

@petermuessig
Copy link
Member

@icostaykov - the chunks are created when the bundler finds dynamic require/import statements - or in some special cases, when the same modules are shared by 2 or more different modules, then the rollup bundler decides to create chunks for this.

With the next upcoming minor version of the ui5-tooling-modules, this may happen more often, since I plan to change the bundling in a way that I pass initially all entry modules and then let rollup decide how to bundle the whole 3rd party more effective. This is necessary to avoid conflicts, e.g. if the same module requires the same other module to avoid multiple packaging of those reused modules in other bundles.

HTH...

@Kalo2412
Copy link

Kalo2412 commented Jan 8, 2024

I would like to reopen this ticket because I have similar issue. My case is with the following third-party lib: @sap-cloud-sdk/openapi where the problem is not the chunks but somehow the lib is not even bundled and transpilled when running on dev server. More information:

  1. I have followed the exact same steps in this link: https://api.sap.com/api/SAP_CP_Neo_Connectivity_Destination/cloud-sdk/JavaScript

  2. I receive the following error in the console:

ModuleError: Failed to resolve dependencies of 'ts/ui/controllers/Planner.controller.js'
-> 'ts/ui/controllers/handlers/some.js'
-> 'ts/services/managers/some2.js'
-> 'ts/services/managers/some3.js'
-> 'ts/generated/SAP_CP_Neo_Connectivity_Destination.js': failed to load 'ts/generated/SAP_CP_Neo_Connectivity_Destination.js' from ./generated/SAP_CP_Neo_Connectivity_Destination.js: 404 - Not Found

PS: The paths are correct so it does not seem to be the problem there.

Can you please check this as well?

Thanks,
Kaloyan

@petermuessig petermuessig reopened this Jan 9, 2024
@petermuessig
Copy link
Member

petermuessig commented Jan 9, 2024

Let me check - but will take a little bit

@petermuessig
Copy link
Member

Hi @Kalo2412 ,

is there any example project you can share?

THX

@Kalo2412
Copy link

Hi @petermuessig , i will attach an example project which is just the ui5 typescript tutorial app with the mentioned lib installed. The error is similar. Thanks in advance.
Example_Project.zip

@Kalo2412
Copy link

@petermuessig
Copy link
Member

Thanks @Kalo2412 - I found a few issues here and there - it's really tricky to make the SDK available via tooling-modules. The issue you reported is just the surface but an issue in the https://github.com/ui5-community/babel-plugin-transform-modules-ui5 - I need to fix the names of the imports to not allow dashes and more reserved characters. But then I stumble in bundling issues... I'll continue investigating it to provide a proper solution for you...

@petermuessig
Copy link
Member

Fix for naming of variables of re-exports: ui5-community/babel-plugin-transform-modules-ui5#122

Will be released with babel-plugin-transform-modules-ui5 version 7.2.7 - but still this doesn't completely fix your issue here...

@petermuessig
Copy link
Member

I just found the following docu from the Cloud SDK guys which explains the usage in React / Angular: https://sap.github.io/cloud-sdk/docs/js/guides/browser

The biggest issue with the Cloud SDK is that is works somehow in the browser but it seams that it wasn't designed from scratch for that use case and therefore using a generic bundling step is cumbersome. In their docu they describe the webpack configuration to bundle it but I wonder if it still works with Angular / React. Anyways, this looks like a challenge.

For UI5 they got a ticket beginning of last year but they gave up in looking into supporting UI5: SAP/cloud-sdk-js#704 😢

@petermuessig petermuessig added the enhancement New feature or request label May 26, 2024
petermuessig added a commit that referenced this issue May 28, 2024
In the previous version the chunks have been sorted into subfolders
which are identified as first module importing the chunks. This
was done as a follow up of #915 which causes 404s when loading
chunks in CDN scenarios. By putting the chunks into the folders
with the name of the module requiring the chunk the module could
be loaded successfully again when using resourceroots for the
module. (implemented in 3.5.x version)

With the enhancement to load the chunks with relative path names
this feature is not necessary anymore and becomes optional so that
it can be re-enabled by providing the config options chunksPath: true.

In addition, the chunks are put by default flat into the resources folder.
By providing the config option chunksPath: "my/chunk/path" you can provide
a subfolder into which the chunks will be clustered into. When using the
config option addToNamespace: true the chunksPath will be appended to
the %namespace%/thirdparty path so that it is relative to the root
where the modules are put into.
petermuessig added a commit that referenced this issue May 28, 2024
In the previous version the chunks have been sorted into subfolders
which are identified as first module importing the chunks. This
was done as a follow up of #915 which causes 404s when loading
chunks in CDN scenarios. By putting the chunks into the folders
with the name of the module requiring the chunk the module could
be loaded successfully again when using resourceroots for the
module. (implemented in 3.5.x version)

With the enhancement to load the chunks with relative path names
this feature is not necessary anymore and becomes optional so that
it can be re-enabled by providing the config options chunksPath: true.

In addition, the chunks are put by default flat into the resources folder.
By providing the config option chunksPath: "my/chunk/path" you can provide
a subfolder into which the chunks will be clustered into. When using the
config option addToNamespace: true the chunksPath will be appended to
the %namespace%/thirdparty path so that it is relative to the root
where the modules are put into.
petermuessig added a commit that referenced this issue May 28, 2024
In the previous version the chunks have been sorted into subfolders
which are identified as first module importing the chunks. This
was done as a follow up of #915 which causes 404s when loading
chunks in CDN scenarios. By putting the chunks into the folders
with the name of the module requiring the chunk the module could
be loaded successfully again when using resourceroots for the
module. (implemented in 3.5.x version)

With the enhancement to load the chunks with relative path names
this feature is not necessary anymore and becomes optional so that
it can be re-enabled by providing the config options chunksPath: true.

In addition, the chunks are put by default flat into the resources folder.
By providing the config option chunksPath: "my/chunk/path" you can provide
a subfolder into which the chunks will be clustered into. When using the
config option addToNamespace: true the chunksPath will be appended to
the %namespace%/thirdparty path so that it is relative to the root
where the modules are put into.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
4 participants