Component-preload.js,Minification and Uglification For Enhancing The Performance Of SAPUI5 application
In this blog, we’ll look at the use of building, Component-preload.js, minification, and uglification for enhancing the performance of application.
SAPUI5 applications are build with the MVC pattern and therefore consist of multiple files, like views or controllers, With fragments, it’s possible to split up parts of views even further into smaller logical units.
Although having a lot of difference files based on their functionality is good during the development, it’s bad when running on a production server. Every necessary file fires a separate network request. You have to wait until all network requests are completed before the app is usable. you may not notice this delay in your corporate network[which is not in my case 😀 😀 :P], but you’d notice in on a mobile phone with a moderate connection speed.
To solve this issue, you can package different files into a single file, a process called bundling. through bundling, your app only has to load a single file instead of all the separate files, which speeds up the loading time of your application because your app has to wait only for a single file to load.
In SAPUI5, this single file is called Component-preload.js . this file contains all the code of your application in a minified version. Minification means removing all unnecessary white-space and comments, Which also decreases the file size. In addition, the javascript source code is also uglified. Ugification means that your source code will not be as readable as before.
Minification via a Grunt Task Runner
You can minify your SAPUI5 application source code via a Grunt task. The Grunt task is called openui5_preload is in Node Package Manager(NPM) called grunt-openui5.
Grunt is a task runner based on node.js. A task runner can run certain tasks, like linting, minification, bundling, executing unit tests. The idea behind a task runner is to automate repetitive work.
Node.js Setup
Setting up Node.js is pretty straightforward:
- Navigate to https://nodejs.org/ and download Node.js
- Follow the installer instructions. You can test the installation by opening your “Node.js command prompt” {not the usual cmd one ;)}
*NPM is installed automatically with Node.js*
Grunt Setup
Now you can install Grunt command-line tool NPM package globally( -g parameter stands for globally) from the command line by typing the following:
npm install -g grunt-cli
after running the install command, you should see a similar output as that shown below. That completes the Node.js and Grunt setup.
Now that you know about the Grunt task runner and Node.js, let’s dive into an example to see the task in action.
Create Gruntfile.js and package.json manually by right clicking on the project name .
The structure of the application is shown below also note the Gruntfile.js and package.json files.
Gruntfile.js contains the task for minifying the SAPUI5 application, and package.json contains all the required modules.
when you run the this application and look at Google Chrome’s NETWORK tab, you’ll see that app-salarycard files requested separately.
Gruntfile.js
Now let’s look at Gruntfile.js
Inside grunt.initConfig is one configuration object, dir, which refers to the name of the webapp(i.e. Projectname– Salarycard) and the name of the destination folder, dist . Then there are three tasks:Copy, clean, and openui5_preload. The copy task is responsible for copying all the files to the dist folder.The clean task removes all the files inside the dist folder.
The actual minification of the SAPUI5 application happens inside openui5_preload . To configure the task, you need to provide the namespace of the application with the prefix setting and the component with the components setting. The cwd property defines the root directory of your application.
In src we have listed all the default settings . When you want to include additional files or exclude certain files, you have to set the src property and list all your desired settings.If you use the src property, the default settings of the src property will be ignored. This means that if you forget to list ‘**/*.view.xml‘, then the view files won’t be minified anymore.
grunt.loadNpmTasks loads various plugins, like grunt-contrib-clean for cleaning directories or grunt-openui5 to minify the application.Those tasks expect different configuration settings, like openui5_preload:{ . . . }, which we previously defined inside grunt,initConfig({. . . }).
At the end, you’ll see grunt.registerTask. Here, we register two tasks:build and default . The default task runs when you type “grunt” inside the command line(Node.js command line).
package.json
Here is package.json file code looks like
name: <any name>
description: <free text>
author: <free text>
We have listed dependencies like grunt-openui5 or grunt-contrib-clean inside the devDependencies setting.This mean that those packages are only needed during development of the application and not when running in production mode.
Now, open the command line and switch to the Salarycard directory, Inside the command line and type “npm install” . As you can see in below screen shot all the required dependencies are installed.
Running NPM install Command:
Now, all the listed dependencies inside package.json are installed in the node_module folder, as you can see below
and check for the below files inside node_module folder, no need to go in depth
Running Grunt
Now, type “grunt” inside the command line to start the minification process. When you look inside your project, you’ll now see the dist folder which contains the Component.preload.js file as shown below.
dist folder with Component-preload.js file
Below image shows an excerpts of the Component-preload.js file, in which all the application files are listed as module and included in the minified source code.
Now, move the Component-preload.js file out of dist folder to WebContent folder of the application.
Below is the folder structure after moving the Component-preload.js file into WebContent folder.
Now, we will open Component-preload.js file to change the file path to load properly.
before change:
after change the Component-preload.js file will look like below [WebContent removed]. As we never provide the WebContent folder path anytime in our development.
If you run the application again and inspect the network trace again in Google Chrome, you’ll see that Component-preload.js is loaded instead of all the separate files shown in below screen shot.
comparison Before and After :
We can observe that number of request reduced to 25 after loading of Component-preload.js file.
Now, we may delete all the un-necessary files/folders like Gruntfile.js, package.json, node_module, dist . {at this point these files are not required anymore because we have achieved our motive i.e. minifing the files}.
Note: if you change any source code in the file you need to run the “grunt” command again to minify the source code again otherwise it won’t work properly.
How To Debug The Application After Minification and Uglification
As we had noticed that after loading of Component-preload.js file our Views, controllers files are not visible anymore in Network trace. So don’t worry there is always a way for the developers :).
We need to add a parameter to the application url i.e. sap-ui-debug=true which will load all the minified files into the Network tab in readable format.
Here we can see our files
Method-2:
You can switch off the Component-preload.js file loading by addling the URL parameter “sap-ui-xx-componentPreload=off”
i.e.:- “http://localhost:8080/Salarycard/index.html?sap-ui-xx-componentPreload=off”
That’s all on Componet-preload.js, minification and uglification, Hope you enjoyed this blog.
***IMPORTANT
Once we Share the application to ABAP server we need to provide a BSP application name starts with “Z” , And the Component-preload.js file will look like below, A file name with 44 characters will be created.
As we have created a brand new BSP application , So the file path won’t work anymore in Component-preload.js file, If you run the BSP application you can still observe the Component.preload.js file loads correctly but along with that all other files like *.view.xml, *.controller.js, *.json etc loads which was’t our requirement, So to avoid this conflict it’s always better to create a BSP application starts with “Z” in ABAP server (ZDEMOSALCAD) and create a project in eclipse with the exact name as BSP application to avoid this conflict in future.
(Thanks to my colleague Sanika for this information)
For example
Create a BSP Application name : ZDEMOSALCAD
Then create Eclipse Project Name with the exact same name : ZDEMOSALCAD
Thanks & regards,
Suman Kumar Panigrahi
Hi!
Interesting post!! Please check my approach with js minification in https://blogs.sap.com/2017/07/08/accelerate-your-ui5-application-with-component-preload-minified/
Best regards
Hi Enric,
Thanks, and yes I had gone through your blog and found it interesting and very helpful while struggling to achieve this, Thanks a lot and keep blogging.
Regards.
Suman Kumar
Hi Suman,
I have followed all steps but the Component-preload.js request GET 404 (not found). Could you please help me on this error?
Structure in my Eclipse project
Content in UI5RepositoryPathMapping.xml file
Structure of the my BSP application
Network trace
Component-preload.js not found !!!
Kind regards,
Norman
Hi Suman,
I'm happy to see your blog post is as recent as Sept 2017. I'm also looking at this topic, however I can't get Component-preload.js to load when I place it next to Component. It no longer 404's for me at runtime, as it always used to.
I have confirmed this across multiple examples; old apps, running with legacy UI5 versions, normal WebIDE, full-stack WebIDE, Trial WebIDE... none of these load Component-preload.js anymore when inspecting + network tab.
When I place my Component-preload.js in my webapp directory to do a test, it is simply ignored. This is running via WebIDE mind you, not serving locally, nor working with Eclipse.
Appreciate any help. Jason
Hi Jason,
Can you please share you folder structure.
Thanks & regards,
Suman Kumar.
Hi Suman, sure:
You can see that it's next to Component.js according to SAP's own template. When running via the WebIDE (the next screenshot below), where the red arrow is, there USED to always be a request for Component-preload.js, but not anymore. Other items are still requested like the resource bundles and 404 when not there. The development component is always used.
You should be able to replicate by choosing any app of yours with Component-preload and implement on a free SCP Trial account. And if you do replicate, then I think the enquiry needs to escalate to SAP.
Jason
Great news Suman & readers,
A colleague identifed the change. The WebIDE applies a URL parameter, "sap-ui-xx-componentPreload=off", by default now. By 'now', I don't mean the change was necessarily recent, only within my attention span to this issue. Removing this URL parameter results in a successful request to Component-preload.js.
This makes sense for WebIDE development, as without this, the presence of Component-preload.js in the main code of the app would be an annoying problem for dev workflow. It appears SAP intend for preloaded/optimized production builds to be arranged from the /dist folder. Lots of debatable decisions there for CI/CD.
Noteworthy also, I tried adding a Run Configuration with a URL Parameter set as sap-ui-xx-componentPreload=on, but this had no effect (must not be a real setting).
Yes Jason you are right, SAP has by default add/appending the URL parameter "“sap-ui-xx-componentPreload=off” in dev client for make the life easier for the developers. :), Another easiest way to un-grunt or un-compress the views and controllers is "ctrl+Shift+Alt+P" where you can check the debugging option and refresh the app to see the actual views and controller source codes.
Hi Jason,
How did u perform the Grunt task in SCP WebIDE? I guess it’s provided by default by SAP if I am not wrong. The above blog is written based on ecliplse IDE, So I have to replicate the same scenario in WebIDE as well.
Thanks & Regards
Thanks for covering important topic.
I have a question, I generated a
Component-preload.js
, but as far as I understand, this file optimizes a loading process of internalSAPUI5
files only. In my project there are quite a lot custom JS and I would like to optimize them as well.The question is how can I establish in
SAPUI5
environmentDEV
andPRD
branches, to separate minified and uglified files from those, who are dedicated for ongoing development.Thanks.
One more question, do I understand it correctly that Grunt-script can be replaced with NPM-script?
Is there any way to make URL parameter "sap-ui-xx-componentPreload=off" inactive/ineffective. Component-preload.js should always load even if URL parameter "sap-ui-xx-componentPreload=off" is entered.