SAP / openui5

OpenUI5 lets you build enterprise-ready web applications, responsive to all devices, running on almost any browser of your choice.
http://openui5.org
Apache License 2.0
2.95k stars 1.23k forks source link

Feature Request: Include core-js and regenerator-runtime polyfills in sap.ui.core #3172

Open pwasem opened 3 years ago

pwasem commented 3 years ago

OpenUI5 version: 1.86.3

Browser/version (+device/version): Any

Description:

As more and more developers want to use latest ECMAScript features when building their apps using UI5, there are more and more custom tasks and custom middlewares for the UI5 Tooling which focus on transpiling code, e.g. using babel such as:

As of babel 7.4.0 it is necessary to directly include core-js (to polyfill ECMAScript features) and regenerator-runtime (needed to use transpiled generator functions) (For details please see https://babeljs.io/docs/en/babel-polyfill).

The issue arises once one need to include these polyfills within the application. Because of the way an UI5 app is loaded and instantiated compared to other frameworks and bundlers, this requires some additional boilerplate:

Prerequisite

Include project shims for the polyfills in ui5.yaml:

---
# 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/: ""

After the project shims have been created there are now two options for actually loading these polyfills as early as possible.

Option 1

Define them 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"
        }
      ]
    }
  }
}

Option 2

Load them synchronously before defining the Component in Component.js:

(() => {
  sap.ui.requireSync('my/app/namespace/thirdparty/core-js-bundle/minified')
  sap.ui.requireSync('my/app/namespace/thirdparty/regenerator-runtime/runtime')
  sap.ui.define(['sap/ui/core/UIComponent'], UIComponent => UIComponent.extend("my.app.namespace.Component", {
    metadata: {
      manifest: "json"
    }
  }))
})()

However both approaches have the limitation that async await syntax will not be allowed in Component.js itself, as this file triggers the initial load of the polyfills.

To avoid this boilerplate and also to eliminate any further build issues both polyfills could simply be bundled and provided within the sap.ui.core as there are already other thirdparty polyfills included:

https://github.com/SAP/openui5/tree/master/src/sap.ui.core/src/sap/ui/thirdparty

One could simply omit any other es6 shims in favour of core-js and also include regenerator-runtime as well.

These would allow to use modern ECMAScript features when developing UI5 apps and also ensure backward compatibility with older browsers.

A full example project can be found here:

https://github.com/pwasem/bookshop-ui

codeworrior commented 3 years ago

I fully understand the pros of including core.js, but this is not the current direction of our thinking. We rather tend to limit UI5 itself (openui5 as well as SAPUI5, but not apps that are using it) to what all browser in our product availability matrix (PAM)*) support out-of-the-box.

Now, that IE11 support is history, this will allow a much broader range of Ecmascript features, but not everything that one can imagine.

@petermuessig I assigned you, maybe you want to comment on this.

*) the PAM has not yet been updated to reflect the end of support for IE11, so don't worry. With 1.88, IE11 support is history

codeworrior commented 3 years ago

Or, maybe, I misunderstood your request and you only want core.js to be packaged (but not bundled by default)? Maybe you can elaborate on that.

The request for including tasks rather goes to the ui5-tooling.

pwasem commented 3 years ago

@codeworrior

My feature request would be to include and load core-js and regenerator-runtime within sap.ui.core itself, unless there is another way to load these or any other scripts or polyfills before loading Component.js despite my two options described above.

As of now this is quite a limitation compared to other frameworks.

Even if the ui5-tooling would include such tasks at some point the the script, polyfills, or resources would need to be loaded by the application itself as shown above.

I am open to any other suggestions and solutions here.

But the overall target should be to enable modern JavaScript development for the UI5 ecosystem.

petermuessig commented 3 years ago

Hi @pwasem ,

I am not yet sure what the best solution for this is. Basically, including it in UI5 is too much "bottle-neck" style IMO. Also what @codeworrior mentioned, with the latest version of UI5 we wanna get rid of most of our polyfills as we are de-supporting IE11. I think we need to have a better and future-proof solution for those kind of polyfills. It should be possible to integrate them easily on demand for applications and also for libraries.

The consumption of the polyfills from NPM packages and using the shims looks and feels good to me. The bigger problem is to find the right point in time / the place where those polyfills are integrated and executed at runtime. It somehow needs to be ensured to execute them even before and code from the application / library is excuted. The manifest.json doesn't look to be such a bad place. The main problem is when those resources will be included. With the manifest-first option for loading Components, we would ensure to load the manifest first and then the resources in the includes could be loaded. Unfortunately, as of today, the resources are included once the first component instance is being created.

@codeworrior - IMO, we may need to re-discuss whether we could have a special place to list polyfills in the manifest.json which could be loaded even before the first instance is being created or change the time when the resources includes are being added. Just food for thoughts right now.

Cheers, Peter