Skip to Content
Author's profile photo Wouter Lemaire

Next generation JavaScript in UI5 using SAP Web IDE

Introduction

The new Full Stack SAP Web IDE comes with integration of Grunt. Grunt is a JavaScript task runner and will automate the build process of your UI5 project. It will, for example, minify the JavaScript files, generate a preload and so on…

There are already two great tutorials on how Grunt works in the SAP Web IDE:

Basic tutorial: https://www.sap.com/developer/tutorials/webide-grunt-basic.html

More advanced tutorial: https://www.sap.com/developer/tutorials/webide-grunt-plugins.html

Grunt offers a lot more than what you see in these two tutorials. It has a lot of Plugins which you can be used to optimize the build process of your UI5 app. You can search for any plugin on the Grunt website: https://gruntjs.com/plugins

This Grunt feature opens a lot of possibilities for UI5 developers that are using the SAP Web IDE. Until now, you still had to use another IDE to use Grunt.

One of these possibilities is Babel. Babel is a compiler to use next generation JavaScript in UI5 project, more precisely ECMAScript 6 also known as ES6.

The problem of ES6 is that it isn’t supported in older browser. As not all customers have the latest version of each browser rolled out in the company, this is a real pain. Still, it’s possible to already use ES6 even if the customer is using older browser versions. To do so, you have two options:

  • Shims and polyfills
  • Transpiler (compiler)
    • A transpiler will convert your ES6 code to another (older) JavaScript (ECMAScript 5 for example) version that’s supported by all browsers. As this will convert your ES6 code to ES5, there is no need to include shims to support new features of ES6.
    • Babel is a JavaScript Compiler that will to this conversion for you: https://babeljs.io/

(Which option that you should choose is still up to you.)

In this blog, I’m going to explain how you can use Babel as a Transpiler/Compiler for your UI5 project in the Full Stack Web IDE.

Configure Grunt

First, we must define the Grunt plugins that we need to build the UI5 project. For Babel, we must include:

  • Babel-core
    • Core library of babel
  • Babel-preset-env
    • Contains the environment for the compiler, this is the recommended preset.
  • Grunt-babel
    • Required to configure Babel in Grunt

The versions of the different components have to match, otherwise you could have unexpected errors.

Package.json will look like this:

{
	"name": "BabelDemo",
	"version": "0.0.1",
	"description": "",
	"private": true,
	"devDependencies": {
		"babel-core": "7.0.0-alpha.19",
		"babel-preset-env": "2.0.0-alpha.19",
		"grunt-babel": "7.0.0",
		"@sap/grunt-sapui5-bestpractice-build": "^1.3.19"
	}
}

We want to combine Babel together with the UI5 best practice build process. Therefore, we must make some changes in the “Grunfile.js”.

  • Babel configuration:
    • Will take all the JavaScript files from the “webapp” folder and put the result in a temporary Babel folder
    • It will NOT take JavaScript files from the library folder. If your library folder has another name, you should change it in the Grunt file.
  • Clean Babel
    • The Babel folder should be cleaned after the build process. For all other folders it is integrated in the UI5 best practice build process.
  • Copy to Debug and Tmp
    • We must change the copy configuration for both debug and tmp copy commands. Instead of copying the JavaScript files from the “webapp” folder, they must use the Babel folder. But ONLY for JavaScript files that are not in the library folder!

By using Babel, it can be possible that you have warnings during the build process. To have more information about a warning, I activated the “stack” option of grunt. This will give a stack trace of warnings and errors.

Gruntfile.js

module.exports = function(grunt) {
	'use strict';

	var webAppDir = "webapp";
	var targetDir = "dist";
	var tmpDir = targetDir + "/tmp";
	var tmpDirDbg = targetDir + "/tmp-dbg";
	var tmpDirBabel = targetDir + "/tmp-babel";

	var config = {
		babel: {
			options: {
				sourceMap: false,
				presets: ['env']
			},
			dist: {
				files: [{
					expand: true, // Enable dynamic expansion.
					cwd: 'webapp/', // Src matches are relative to this path.
					src: ['**/*.js'],
					dest: tmpDirBabel, // Destination path prefix.
					//ext: '.js',   // Dest filepaths will have this extension.
					//extDot: 'first',   // Extensions in filenames begin after the first dot
					filter: function(filepath) {
						return !filepath.match(new RegExp('webapp/libs', 'gi'));
					}
				}]
			}
		},
		clean: {
			build: [targetDir],
			cleanBabel: [tmpDirBabel]
		},
		copy: {
			copyToDbg: {
				files: [{
					expand: true,
					src: "**/*.js",
					dest: tmpDirDbg,
					cwd: tmpDirBabel,
					filter: function(filepath) {
						// prevent js from localService to be copied
						return !filepath.match(new RegExp(webAppDir + "(\\/|\\\\)localService", "gi"));
					}
				}, {
					expand: true,
					src: 'libs/**/*.js',
					dest: tmpDir,
					cwd: webAppDir
				}, {
					expand: true,
					src: "**/*.css",
					dest: tmpDirDbg,
					cwd: webAppDir
				}]
			},
			copyToTmp: {
				files: [{
					expand: true,
					src: '**/*.js',
					dest: tmpDir,
					cwd: tmpDirBabel,
					filter: function(filepath) {
						// prevent js from localService to be copied
						return !filepath.match(new RegExp('build' + '(\\/|\\\\)localService', 'gi'));
					}
				}, {
					expand: true,
					src: 'libs/**/*.js',
					dest: tmpDir,
					cwd: webAppDir
				}, {
					expand: true,
					src: '**/*.css',
					dest: tmpDir,
					cwd: webAppDir
				}, {
					expand: true,
					src: 'localService/metadata.xml',
					dest: tmpDir,
					cwd: webAppDir
				}, {
					expand: true,
					src: '**/*',
					dest: tmpDir,
					cwd: webAppDir,
					filter: function(filepath) {
						// prevent js and css files and contents of webapp/test from being copied
						return !filepath.match(new RegExp("(" + webAppDir +
							"(\\/|\\\\)test|${webAppDir}(\\/|\\\\)localService|\\.js$|\\.css$|\\.ts$|\\test.html$)", "gi"));
					}
				}]
			}
		}
	};

	grunt.loadNpmTasks('grunt-babel');
	grunt.loadNpmTasks("@sap/grunt-sapui5-bestpractice-build");
	grunt.config.merge(config);

	grunt.registerTask('default', 'runs my tasks', function() {
		var tasks = [
			'clean:build',
			'babel',
			'build',
			'lint',
			'clean:cleanBabel'
		];

		// Use the force option for all tasks declared in the previous line
		// grunt.option('force', true);
		grunt.option('stack', true);
		grunt.task.run(tasks);
	});
};

 

Configure ESLint

Using ES6 in the SAP Web IDE will result in unwanted errors on ES6 syntax. You can avoid this by following these steps:

Go to the Project Settings ==> Code Checking ==> Validator Configuration and add “es6”:true to “env”:

Use ES6

Now start using ES6! As an example, I created a basic UI5 project in which I’m using a few ES6 features to do some array manipulations.

I have an array with some numbers, convert it to objects and get the odd and even numbers out of it. On the view, I show the three lists.

Controller:

View:

The app will look like this:

After running Grunt

After running Grunt, the controller will look like this in the “dist” folder:

If I run the app from the dist folder, it will show the same result:

You can find the complete source code (including “dist” folder) on github: https://github.com/lemaiwo/UI5Babel

 

More ES6 features: http://es6-features.org

 

Start using ES6 in your UI5 project! 🙂

Assigned Tags

      22 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Serban Petrescu
      Serban Petrescu

      Nice Wouter! This is fairly similar to what I have presented recently in some SAP Conference: building ES6 libraries for UI5. It's nice that you got it to run also on WebIDE (I usually use VSCode for this).

      Author's profile photo David Garcia
      David Garcia

      Will it only work with webide fullstack or with the normal one too?

      Author's profile photo Michal Keidar
      Michal Keidar

      Only the SAP Web IDE Full-Stack has the Grunt capability.

      Author's profile photo Fábio Luiz Esperati Pagoti
      Fábio Luiz Esperati Pagoti

      I wonder why someone has decided to fork Web IDE and create a "Full stack" one. I would never switch IDE all the time to run grunt or do a simple task like that.

      Author's profile photo Michal Keidar
      Michal Keidar

      Hi Fabio,

      You are not expected to switch IDE every time you want to run a Grunt task..

      Currently SAP Web IDE has several versions but this is only because we're in transition phase. Our goal is to have one IDE, with all current capabilities. We didn't dimply "fork" Web IDE, the entire backend has changed (from Orion to CHE).

      If you're interested in more information, please find my blog.

      Regards,
      Michal.

       

      Author's profile photo Sergio Guerrero
      Sergio Guerrero

      thanks for sharing this blog. it is very informative and helpful.

       

      is this only working on current version of Web IDE? would it work on the  WEB IDE version that comes with HANA SP12 ?

       

       

      Author's profile photo Michal Keidar
      Michal Keidar

      Only the SAP Web IDE Full-Stack has the Grunt capability.

       

      Author's profile photo Christopher Solomon
      Christopher Solomon

      Very nice!!!! Used to Babel from "other" programming (yes, non-SAP work...*gasp*!!!).....so it is cool to see it here now. Thanks for the info!

       

      Author's profile photo Alexander Chan
      Alexander Chan

      Thanks for sharing, just a few questions and comments:

      1. The last time I looked at the preview versions the grunt build task had to be run each time we want to test.  Do you know if this has changed and if we can just have it running and building watching for changes?  it would be nice to optionally have a live reload or hot reload.
        Testing in chrome can get us the es6 features but it would be nice to test against the dist version always.

      This is more for someone from sap:

      Are there plans to allow different task runners?  Many of us have a preference for the more powerful webpack and giving us this customization would be one less reason to use a local build setup.

      Thanks!

      Author's profile photo Wouter Lemaire
      Wouter Lemaire
      Blog Post Author

      Good points you made.. Think currently it's not possible but maybe in the feature...

      Author's profile photo Former Member
      Former Member

      Thanks for sharing. I have 2 questions.

      1. When we release the project, how to deploy the code? Release the code in dist folder? And how to release code in dist foler?
      2. If we have the es6 version code to do the code check on Jenkins, the task will fail. But the compiled code in dist folder is usually ignored in git. How can we connect the develop environment to the jenkins env?

      Thank you and Best Regards!

      Author's profile photo Wouter Lemaire
      Wouter Lemaire
      Blog Post Author
      1. just deploy it like before. It will generate a dist folder and deploy that folder to the cloud or your abap system.
      2. In case your using jenkins, you could (not sure) use jenkins to execute the build (which will generate the dist folder) after the es6 validation

      Gr,

      Wouter

      Author's profile photo Jacques Duparc
      Jacques Duparc

      Hi Wouter,

      great post, thanks for sharing.

      I have tried it and find out that method Array.find is not converted. Do you have any idea how to change the grunt file in order to make it work?

      Cheers, Jacques

      Author's profile photo Wouter Lemaire
      Wouter Lemaire
      Blog Post Author

      You need to include babel-polyfill yourself, check the comments here:

      https://github.com/babel/babel-preset-env/issues/210

      Kr, Wouter

      Author's profile photo Jacques Duparc
      Jacques Duparc

      Hi Wouter,

      thanks for the answer. Actually I already found this page, but I was not able to adapt the grunt file in order to make it work with babel-polyfill, that's why I asked here.

      regards, Jacques

      Author's profile photo Sylvain V
      Sylvain V

      Hi Wouter,

      I'm using ES6 in my webide but I'm facing a big problem with outline tab : if I use arrow function, the outline doesn't work anymore.

      Is there as way to solve this ?

      thanks

      Author's profile photo Wouter Lemaire
      Wouter Lemaire
      Blog Post Author

      I have the same problem, no solution found yet. You could use VSCode instead... https://blogs.sap.com/2019/08/30/migrate-ui5-apps-to-ui5-tooling-in-your-local-ide/

      Author's profile photo Sumit Kumar Kundu
      Sumit Kumar Kundu

      Hi Wouter Lemaire ,

      Thanks for the wonderful tips. I have created a Cloud Foundry MTA project with HTMLS5 repository and added "es6":true in project settings ESlint config. Still the ES6 statements is being highlighted as error.

      Also, I have a question: the babel and grunt configurations mentioned is only needed for build of the project, right?

      Regards,

      Sumit

      Author's profile photo Wouter Lemaire
      Wouter Lemaire
      Blog Post Author

      I have the same problem, not able to change this. Will be solved in the new version or you could switch to VSCode: https://blogs.sap.com/2019/08/30/migrate-ui5-apps-to-ui5-tooling-in-your-local-ide/

      Author's profile photo Dimitar Fenerski
      Dimitar Fenerski

      Hi Wouter Lemaire

      nice blog, helped me a lot, thanks for sharing.

       

      However in my case, what i needed was part of the ES6+/ES7 EcmaScript specification (spread syntax, Promise.all).

      To overcome this, only changes to the project.json file were needed, the provided solution was sufficient for the rest (thanks again).

       

      Here is how the project.json should look like, to support the mentioned features:

      {
      	"name": "MyAwesomeFiori",
      	"version": "0.0.1",
      	"description": "",
      	"private": true,
      	"devDependencies": {
      		"babel-core": "^7.0.0-beta.41",
      		"babel-preset-env": "2.0.0-alpha.19",
      		"grunt-babel": "8.0.0",
      		"@sap/grunt-sapui5-bestpractice-build": "^1.3.19"
      	},
      	"dependencies": {
      		"@babel/core": "^7.10.1",
      		"@babel/plugin-proposal-object-rest-spread": "^7.10.1"
      	},
      	"scripts": {
      		"build": "ui5 build --include-task=generateManifestBundle generateCachebusterInfo"
      	},
      	"ui5": {
      		"dependencies": [
      			"@sap/ui5-builder-webide-extension"
      		]
      	},
      	"babel": {
      		"plugins": [
      			"@babel/plugin-proposal-object-rest-spread"
      		]
      	}
      }
      

       

      a babel plugin was needed, as the core does not support this out of the box. It may be possible to extend the babel configuration in a separate file, but I have not tested this.

      If one needs to add it to existing project, I found it handy to run Build->clean npm Folder and Build->Build Project until it works. Then a deploy to the cloud will work as well.

      Best regards,

      Dimitar.

      Author's profile photo Martin Zaman
      Martin Zaman

      Since 3 hours this is not working anymore. Any hints?

      Author's profile photo Avishek Sharma
      Avishek Sharma

      Provided VSCODE/BAS has Node support, We can write direct ES6 code in UI5 without any modifications inside BAS/ VSCODE ?

      Thanks.