ui5-community / babel-plugin-transform-modules-ui5

A Babel transformer plugin for OpenUI5/SAPUI5. It allows you to develop UI5 applications by using the latest ECMAScript or TypeScript, including new syntax and objective oriented programming technology.
MIT License
34 stars 16 forks source link

modules with @scope end up in dependency load failure #61

Closed freakadunse closed 1 year ago

freakadunse commented 3 years ago

hey there!

i am using the plugin to transform my typescript code to ui5 which works pretty well. But i have one issue:

We're hosting a onPremise git for the npm registry, which works with @scopes. So my package is @scope/package-name.

As soon as i import the package and try to run the page, i'll get the following error:

The following error occurred while displaying routing target with name 'Overview': ModuleError: Failed to resolve dependencies of '<Application>/controller/Overview.controller.js' -> '@<scope>/<module>.js': failed to load '@<scope>/<module>.js' from https://sapui5.hana.ondemand.com/resources/@<scope>/<module>.js: script load error - For sure, my package does not exist in the sapui5 hana ondemand resources :-)

The generated define also includes the non existing module: sap.ui.define(["../model/Formatter", "./BaseController.controller", "@<scope>/<module>", "sap/ui/core/mvc/Controller"], function (__Formatter, __BaseController, __Validator, Controller) {

Any idea how to get this working again with @scope-modules?

Thanks!

BR Pascal

freakadunse commented 3 years ago

push: Any idea?

seems like every module that i import from node_modules won't work. I have tried to include it with project shims, also doesn't work :(

Elberet commented 3 years ago

Generally, this project only does transpilation - i.e., it will convert import { Foo } from "./lib/foo" into the appropriate parameters for the sap.ui.define() call and a few helper calls in order to extract Foo from whatever the ./lib/foo file returns.

It is not, however, a module packager. If you import "./lib/foo", then you are responsible that the file ./lib/foo.js exists at runtime or, more accurately, that UI5's loader can resolve the given string to some loadable file that actually exists - but that is out of a Babel plugin's scope and will typically require a more involved build pipeline for your project. @sap/ui5-builder tries to do some of these things, but it may be difficult to get it to pull non-UI5-library npm packages into the UI5 app.

If push comes to shove, you could do this as a workaround:

  1. Prepare a shim like this:
    sap.ui.define([], function() {
    return {
    moment: require("moment"),
    lodash: require("lodash"),
    other: require("@scope/other")
    }
    });
  2. Run that through webpack and place the result in your UI5 project at e.g. ./lib/vendor-bundle.js.
  3. Import referenced libraries with import { moment } from "./lib/vendor-bundle".
  4. Optional: Automate steps 1 and 2.
freakadunse commented 3 years ago

Hi Elberet,

many thanks for your response.

I do understand that it's not Babels scope to be a module packager. In the meantime, i have tried more ways to get things working.

The @scope/other module now get's compiled/transpiled to ui5 executable JavaScript with sap.ui.define. This is also available in the npm package. There's a seperate task to copy the used @scope libraries to a resources folder in the resulting webapp-folder.

However, there is only one issue remaining. The Babel transformation works like charm, except the imports of the resulting sap.ui.define are not correct for the @scope modules. It tries to load these resources from the hana-on-demand CDN, which is not correct in my case.

So to have it working, the only thing i need to do is replace the import-path for the @scope modules used to the files in the resources-folder i copy with the seperate task.

TL;DR: Is there a configuration/path-mapping for the modules, that are used for the sap.ui.define imports?

Otherwise i'd implement a new seperate Babel task to replace the strings, if they match npm packages in my package.json.

Elberet commented 3 years ago

That's the UI5 loader's default logic at work. If an element in the first argument array to sap.ui.define does not look like a relative path - i.e. does not begin with a . -, the module is resolved through its prefix configuration which will ultimately map everything to the URL from which you loaded the UI5 bootstrapper.

In other words, you need to arrange for the define call to reference to your npm packge not by the package name but by the bundled package's filename within your webapp folder. For example, you could simply import thing from "./lib/vendor/@scoped/thing" (if that's where you've placed the bundled package), or perhaps use the babel plugin's modulesMap option to map from the npm package name to the desired relative path.

Elberet commented 3 years ago

The documentation mentions modulesMap but gives no examples, but you can refer to the test code. Using a function could allow you to read mappings from a previous step of your build pipeline.

petermuessig commented 1 year ago

Hi @freakadunse ,

normally all unknown resource paths are loaded relative to the UI5 bootstrap URL. The scope is just seen as a namespace and the dependency isn't being resolved at all with the babel plugin. This needs to be handled either by the UI5 runtime or by the UI5 tooling.

In the meantime, a UI5 tooling extension is handling the inclusion of third-party/OSS components from NPM packages. When using the UI5 tooling you can add the ui5-tooling-modules and include those NPM packages into your project. With the option addToNamespace you even get application local dependencies.

For more details check out the ui5-tooling-modules.

Closing this issue, as this isn't related to the babel plugin.

Cheers, Peter