Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
Nigel_James
Active Contributor

Putting all the tasks together

If you have been following along in this series we have talked about the need for post processing in JavaScript, the different scenarios in UI5land and getting setup with node and grunt.

This is the blog that you have all been waiting for ... Putting all the tasks together.

In the intro we talked about:

  • minifying code
  • creating debug (dbg) versions
  • creating the preload file
  • zip up the built files
  • deploying to the app server
  • making an easy command to use

In the last blog we ticked off the first task, minifying and using a grunt task so that we dont have to repeat all this grunt code in every project. Instead, we have one main grunt task folder with all the build instructions and refer to it for every project.

I am going to save the deployment for the last blog in this series and in this one we are going to cover creating debug, preload and a build command. In fact let's do them backwards. Let the last be first!

A build command

I am running this on windows and hence using powershell and I am guessing this will suit most of you and those using macOS or linux will be able to modify this quite easily.

As I explained in my last post I am using grunt-source to handle the let's not rebuild the wheel for every project.

This means we can have a folder structure like this:


c:\build\_build\
             \project1\
             \project2\
             \project3\







With all the grunt assets in the _build folder we can execute the grunt-source command in anyone of the project folders.


PS C:\build\GruntDeployCrashTestDummy> grunt-source    
Running: grunt







The problem I have with this is that what does grunt-source mean? Not really much to me when I come to building a project. So lets create an alias to grunt-source in our powershell profile.

You can test for your profile in Powershell by issuing this command: Test-Path $profile

If it returns false then issue this command: New-Item -path $profile -type file -force

If you need to know where your profile is type $profile on the powershell command line.

Once you have this profile file you can open it in your favourite text editor Sublime text or Atom and add the following line: Set-Alias build grunt-source

This means that we can now type build on the command line to build our project.

If you issue the grunt-source or build command with no parameters it will run the default task in your grunt file.

My default task does all the tasks I mentioned above except for deployement.

Creating a pre-load file.

The preload file is a pretty awesome way to improve the speed of your app. It takes all the controllers and views and appends a minified version into one file. When UI5 requests your app resources and finds a preload-file it will load this and then look in this file for all other resources.

The "problem" is that ui5 will always look for the prolaod file and this will cost you lets say 25 ms. In some of my testing a hit on the preload file cost 55 ms and then it doesnt have to load any more files in your app, just your oData calls.

You will find the OpenUI5 Preload task on npm.

Here is my task definition to add to my Gruntfile.js


openui5_preload: {
    component: {
        options: {
            resources: {
                cwd: '.',
                prefix: '<%= grunt.source.nsPrefix %>'
            },
            dest: 'build/WebContent/'
        },
        components: true
    }
},








A couple of points to note here. If you look in the last blog where defined the project.json for each project, there in the grunt-source section and it is here that I define the namespace for the project.

This is a required parameter for the preload build.

The other thing to note is build paths. I am taking everthing from the current directory '.' and building it into the preload. The defaults in the task take care of what files to look for. My destination is set as a build directory that can later be zipped ready for deployment. I added the WebContent sub-directory as previous deployments had been with SAP HANA Studio which adds this folder. So to keep things consistant I did the same. You can remove this if you wish.

Creating debug versions of your JavaScript source

This was one of the trickiest things to get right.

To explain why I will show my default definition and the order the tasks run in.

grunt.registerTask('default', ['clean',  'checkout', 'openui5_preload', 'copy', 'uglify', 'zip']); 


This is the set of tasks that will run when I just type build on the command line.

In turn it will clear out the directories used for the build process, it gets the lastest from source control, it creates the preload, copies existing source as debug versions, minfies the code and then zips up the whole build directory.

One of the issues is that once there are files in your build directory, you don't want these files being picked up by the later tasks. The files created by the copy process don't need to be minified. You just have to be vigilant about the source directories. Also the controller.js files are so named so they can be found by convention by that name. That means the debug version of main.controller.js is not main.controller-dbg.js but main-dbg.controller.js

.

Interestingly projects like jQuery have the convention that readable source is main.js and minified versions are main.min.js. UI5 has it the other way around in that readable versions are main.dbg.js and minified versions are main.js. This bugged me for a while and then I realised that it enabled you to deploy debug versions to production and have the speedy minified versions being loaded and the debug versions loaded if you need to check an issue.

Here is the copy task in all its glory.


copy: {
    main: {
        files: [{
            expand: true,
            src: [ './**', '!./build/**', '!./zip/*'],
            dest: './build/WebContent/',
            rename: function(dest, src){
                // this.js -> this-dbg.js
                var destinationFilename = "";
                if(src.search('controller') > 0){
                    destinationFilename = dest + src.replace(/\.controller\.js$/, "-dbg.controller.js");
                } else {
                    destinationFilename = dest + src.replace(/\.js$/, "-dbg.js");
                }
                // grunt.log.writeln(destinationFilename + " | " + src);
                return destinationFilename;
            }
        },
        {
        expand: true,
        src: ['.Ui5RepositoryUploadParameters'],
        dest:  './build/'
    }],
},
other: {
// ...
}
}






Lines 1 - 2 set up the copy task. In fact you can have several sets of copy by defining them at the main task level and then refering to the task as copy:main or copy:other. If you just have copy it will do all the copy sub tasks.

Lines 3 - 6 set up the files to be copied and the destination. On line 5 we include the whole current directory and all subdirectories and then exclude the build and zip directories.

Lines 7 - 19 is how we define renaming the files. The whole point of this task is to create the -dbg copies of the source. This function tests for the controller files and js files and inserts the '-dbg' in the correct place.

Lines 22 - 26 is a second set of files for this task to copy. It is just one file the .Ui5RepositoryUploadParameters file that contains the parameters required by the ABAP upload program. It needs to be in the root directory to be read correctly by that program.

One more thing

By now you have all the tasks to able to do the main part of creating a build system for UI5. There are a couple of tasks like clean and checkout I haven't covered but the last one I will cover in this blog is the zip. Once all the code is coralled into the build directory it is zipped up ready to be loaded to the target app server and added to a transport.

The zip task is pretty easy but there is one trick. As we are loading the main content into the WebContent directory we need to copy the .Ui5RepositoryUploadParameters file in separately at the higher level. This file is used by the ABAP loading program and needs to be at the root directory.


zip: {
        all: {
        cwd: './build',
        src: ['./build/.Ui5RepositoryUploadParameters', './build/WebContent/**'],
        dest: './zip/<%= grunt.source.zipfile %>'
    }
},





If you add all this together with one build command you create zip file in just the right way ready to be deployed to your ABAP system. That is what we will look at in the next and last blog in this series.

<-- Previous blog: Getting our grunt on   Next blog : Deploying to the Gateway Server -->

5 Comments
Labels in this area