Bootstraping OpenUI5 from single JS file - sapui5

OpenUI5 documentation suggests starting work by using a library loaded from CDN:
<script id="sap-ui-bootstrap"
type="text/javascript"
src="https://openui5.hana.ondemand.com/1.42.6/resources/sap-ui-core.js"
data-sap-ui-theme="sap_belize"
data-sap-ui-libs="sap.m,sap.ui.table"></script>
Unfortunately, this approach means load cascading 4 scripts on startup:
sap-ui-core.js
sap/ui/core/library.js (why ?)
sap/m/library.js
sap/ui/table/library.js
Is there way to bundle this four libraries into one script file?

Unfortunately, this approach means load cascading multiple scripts on startup:
The cascading behavior is mostly due to missing an option that tells the framework to load UI5-libraries and other modules asynchronously. In order to fix it, please add the following attribute too:
data-sap-ui-async="true" // available since 1.58.2 --> Replaces preload="async" *
data-sap-ui-preload="async" // for 1.58.1 and below
* Prerequisite: Is Your Application Ready for Asynchronous Loading?
Is there way to bundle these four libraries into one script file?
Yes; with a self-contained build (e.g. ui5 build self-contained --all ), you can reduce the size of your application as well as number of requests by bundling the required modules into a single file sap-ui-custom.js
In the above screenshot, for example, sap-ui-custom.js contains only the required modules from sap.ui.core-, sap.m-, sap.ui.table-, and sap.ui.unified-library, in addition to application related resources such as the controllers, views, etc..
See openui5-sample-app and the UI5 tooling for official documentation.

Related

Bootstrapping ushell_abap for variant persistence

I have a FIORI application (lunched from launchpad) in which I am using unified shell to persist variants.
In my index.html, I first bootstrap the ushell_abap and then ui bootstrap like this
<script id="sap-ushell-bootstrap" src="https://sapui5.hana.ondemand.com/1.90.0/resources/sap/ushell_abap/bootstrap/abap.js"></script>
<script id="sap-ui-bootstrap" src="https://sapui5.hana.ondemand.com/1.90.0/resources/sap-ui-core.js"
data-sap-ui-libs="sap.ushell, sap.collaboration, sap.m, sap.ui.layout, sap.ui.ux3"
data-sap-ui-theme="sap_belize"
data-sap-ui-resourceroots='{"cvg.wallapp": "./"}'
data-sap-ui-compatVersion="edge"
data-sap-ui-async="true"
data-sap-ui-frameOptions="trusted"
data-sap-ui-bindingSyntax="complex"
data-sap-ui-oninit="module:sap/ui/core/ComponentSupport">
</script>
My app works fine, including variant persistence when running in localhost.
I now deploy the APP to my Fiori server and the bootstrapping process falls apart.
It completely fails to load my theme and associated styling (no custom styling just using the belize theme).
In the console I get the following errors:
includeStylesheet-dbg.js:77 GET https://xxxx:yyyy/sap/public/bc/themes/~client-810/~cache-Bo-MdJE9H9k-CMXXsBrbgsL9ZXQ/UI5/sap/suite/ui/commons/themes/Fiori_LP_Home_Theme/library.css net::ERR_ABORTED 404 (Not found)
One or more parameters could not be found. - sap.ui.core.theming.Parameters
As soon as I remove the bootstrapping of ushell_abap everything works (except the persistence of variants of course).
I have exhausted google searches and reading through the ushell documentation here https://sapui5.hana.ondemand.com/sdk/#/api/sap.ushell
Anyone with an idea on why bootstrapping is failing when truing to use ushell_abap ?
The main issue here was that the app was using a different version of the css libraries than the bootstrap libraries which caused errors (in this case core had new elements in css styling not available in the old css library for core).
If your APP is set up as a standalone APP as explained by Benedikt Kromer and you bootstrap to a specific sapui5 version in the index.html, you can force the app to use the same version css libraries by applying the style to the core on init of the main app.
In on init I just added:
sap.ui.getCore().applyTheme("sap_belize");
This forced the app to load css libraries from the same version I used to bootstrap.
You can see this by watching the network tab in developer tools.
I think you missed one key aspect of the launchpad.
"launched from launchpad" could mean:
It is opening a new tab - standalone -> no need to mention launchpad in the question.
Staying in the same tab - standard/desired setup.
If (1) and you try to load the launchpad theme in your 1.90.0 app. Make sure the ui5 version match exactly.
"parameters could not be found" Could indicate your Theme was create for an older UI5 version.
Possible solutions:
You could generate a theme, matching the standalone ui5 version upload it into an own BSP.
You can ignore the error, there may be some
ui-glitches.
In any case 404 errors indicate also that you didn't link the theme correct in the first place.
If (2), then your index.html is never called. UI5 is starting from the component.js. Hence all your bootstrapping there dosen't count.
In this case index.html is only the playground for local development.
For the shell, this is already in place. I'm not sure why you want to load it again.

How to reduce loading time of flutter web app

As of now, we can launch a flutter web app as a single file that will load at once hence taking a lot of time and bandwidth to load which is not ideal, is there any way to load only a single page at a time, not the whole web app. By this I mean, load a widget at a time.
Any suggestions will be appreciated.
after spending a lot of hours trying to solve this situation, I found a solution to speed up the first load of the app.
I saw that my main.dart.js was being downloaded and then, after that, the main.dart.js was triggering the download of the canvaskit.wasm file, this means that my app was starting on a cascade mode, avoiding downloading both files in parallel.
So my solution, after many many many attempts is based on adding only 2 lines of code to the index.html file (.../project_folder/web/index.html).
Inside the <head>...</head> tag insert this two lines:
<script src="https://unpkg.com/canvaskit-wasm#0.33.0/bin/canvaskit.js"></script>
<link rel="preload" href="https://unpkg.com/canvaskit-wasm#0.33.0/bin/canvaskit.wasm" as="fetch" crossOrigin="anonymous">
I know hardcoding these URLs it's not a good practice, but, you will only need to change them if you update Flutter. I'm using Flutter 2.10.1 that uses CanvasKit 0.30.0, and when you build the web app, the generated main.dart.js has a hardcoded URL inside.
If you are going to add those 2 lines to your index.html file, I recommend you to build the web app, and open the main.dart.js file and search for "canvaskit-wasm", there you will find which is the URL you should use (something like "https://unpkg.com/canvaskit-wasm#0.33.0/bin/").
It's giving me a good improvement for the initial loading time! So, hope it works for you too!
Yes, you can load the Flutter web library, only when it is called using Deferred/Lazily loading. Here I copy/paste from Dart documentation:
Lazily loading a library
Deferred loading (also called lazy loading) allows a web app to load a
library on demand, if and when the library is needed. Here are some
cases when you might use deferred loading:
To reduce a web app’s initial startup time.
To perform A/B testing—trying out alternative implementations of an algorithm, for example.
To load rarely used functionality, such as optional screens and dialogs.
And here an article related to this topic.

what is the purpose of these angular2 imports?

I am a newbie in angular2 and want to know the purpose of following imports we do in our angular2 app.
<script src="node_modules/es6-shim/es6-shim.min.js"></script>
<script src="node_modules/systemjs/dist/system-polyfills.js"></script>
<script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="node_modules/rxjs/bundles/Rx.js"></script>
<script src="node_modules/angular2/bundles/angular2.dev.js"></script>
<script src="node_modules/angular2/bundles/http.dev.js"></script>
so my questions regarding these imports are:
what are these imports for?
does the sequence of these imports metter?
are there any other useful imports that we must be aware of?
Thanks in advance.
I don't see any imports in your code sample. Its just including the files of various libraries into web page. If you read some of them one by one:
es6-shim.min.js - adds ES6 language features to browsers (full list)
Rx.js adds Observables library (GitHub RxJS)
http.dev.js - adds angular2 $http module to make requests
So you can google each of the names and figure out for yourself if that's applicable for your project.
More on modules and actual imports in ES2015/ES6 you can read here https://ponyfoo.com/articles/es6-modules-in-depth for example.
"useful imports that we must be aware of?"
Totally depends on your needs. By I assume angular2.dev.js and http.dev.js would be a good to start.
"does the sequence of these imports matter?"
Not now, but only if you're using proper module system so that browser can load missing parts before executing the blocks that depend on them. And also the loader file (system.js/require.js) should be in the first before all the other files.
Here are the details about what you specified in your script elements:
The two first files aren't necessary if you use TypeScript and have configuted ES5 output.
angular2-polyfills.js - Contains ZoneJS (to trigger change detection - see What is the Angular2 equivalent to an AngularJS $watch?) and reflect-metadata (to set metadata on objects from decorators)
system.src.js - SystemJS, the library that manages modules. In short when you use import and export in TypeScript the corresponding compiled code relies on it.
Rx.js - RxJS, a library that provides an implementation of Reactive Programming concepts. In short, it provides an implementArion of observables and their operators. EventEmitters, HTTP rely on this.
angular2.dev.js - Angular2 core bundle
http.dev.js - HTTP support of Angular2

Moving from requirejs to systemjs: managing paths

I'm in the process of migrating to systemjs, mainly given it's support of modules which makes moving to ES6 simpler.
The systemjs CSS plugin allows for elegant imports like this:
System.import('bootstrap/css/bootstrap.css!');
But this loads asynchronously, so it's not practical for loading CSS that needs to be loaded before the rest of the server-generated page. So I have to revert to cumbersome package URLs. (which will break when versions change -- and seems to be generally quite hacky -- since JSPM is supposed to be managing these details?)
<link rel="stylesheet" href="/res/packages/github/twbs/bootstrap#3.3.5/css/bootstrap.css">
Is there a best practice? In fact, are there any useful examples of the practical use of systemjs?
You might hide the body, create a javascript module that loads your assets and show the body when the assets have loaded:
assets.js
import 'bootstrap/css/bootstrap.css!';
Then in your index.html file:
System.import('assets.js').then(function(){
//Now your styles are loaded. You may fade in/display your content.
document.querySelector('body').style.display = 'block';
}); //Add the JS extension according to your SystemJS configuration

How does jQuery.sap.require work?

Does SAPUI5 load the libraries each time I call jQuery.sap.require("someLibrary")?
For instance if I am calling the above statement in multiple modules in my application, is "someLibrary" loaded multiple times also?
In case someone still considers to use jQuery.sap.require, be aware that it sends only synchronous XHRs which should be avoided.
The use of jQuery.sap.require is synchronous and considered as "bad practice" because syncXHR is deprecated by the Web Hypertext Application Technology Working Group. (Source: Modules and Dependencies)
Instead, the current best practice is to use sap.ui.define or .require for asynchronous module loading:
<!-- Enable asynchronous module loading in index.html (available since 1.58.2) -->
<script id="sap-ui-bootstrap" src="..." data-sap-ui-async="true" ...>
sap.ui.define([ // or .require
// modules to load
], function(/* modules available once loaded */) {
// ...
});
Source: Asynchronify Your App by Arnd vom Hofe. Note: anonymous sap.ui.define can be called only once at top-level.
Same as jQuery.sap.require, the API sap.ui.require([/*...*/]) fetches the modules also only once depending on their internal states.
For more information, please take a look at the topics under Modules and Dependencies.
Sync XHR is deprecated not only by the web platform generally, but will be also replaced by UI5 gradually with a new set of APIs.
Source: UI5 Evolution by Peter Muessig
Consequently, jQuery.sap.require and jQuery.sap.declare are now deprecated and will be removed in the next major UI5 version (aka. "Legacy-free UI5")!
The lib is only loaded once. You can find this information in the SDK
https://sapui5.hana.ondemand.com/sdk/#docs/guide/ModularizationConcept.html
Module Loading
As mentioned already, modules are loaded by calling function jQuery.sap.require with the name of a required module. The framework then checks whether the named module is loaded already. If so, the function simply returns. Otherwise it tries to load and execute the module synchronously. If any of these two steps fails, an exception is thrown and execution of the calling module thereby is disrupted.
When you call this function with some library, it checks that given library is loaded or not using associative array. If the library is loaded, then it returns null. And if the library is not loaded, then it loads the library using sjax call and after a success of the sjax call, it sets the library name as key into associative array.
The libraries are loaded once. This can be seen in the network tab in chrome developer tools.
Also check the documentation as pointed by cevou here:
https://openui5.hana.ondemand.com/#/topic/91f23a736f4d1014b6dd926db0e91070