Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
Former Member

Nowadays, when mobile version of corporate web application is not something esoteric, but a must requirement for every app that claims to be successful, a lot of buzz is about modern and fancy web technologies like HTML5 and CSS3. SAP as one of the market leaders is not going to stand out of track and proactively contributes to mobile web development. However, rapidly growing client-side development brings it’s own challenges, that not only the corporate, but common developers as myself should deal with.

When I start to work on a new project, I prefer to spend some time to set up development environment to make it more convenient and develop with pleasure. The most common issue that majority of client-side developers are dealing with is that modifying static resources that are not to be compiled, but do part of some deployable unit of complex web application like SAP Enterprise Portal, requires compilation of the whole deployable unit and its deployment to target web container as well. And this is absolutely not acceptable process for rapid development, when almost each row of code should be checked on the fly in the browser. There are several technics of how to avoid annoying compile & deploy cycles during the work on Java Script and CSS. In this post I’m going to describe one of them that I’m using in my day-to-day work. Besides of it I will explain how to perform merges of static resources and compile LESS files to CSS on the fly.

Understanding The Flow

The first thing that is need to be done is to understand how the static resources will be delivered to the browser from different place without performing any changes in the web application or its web container configuration. The following sequence diagram explains how it will be done.

The flow is as follows:

  1. Instead of directly accessing application, browser accesses proxy server (to get something dynamically generated like index.jsp);
  2. Proxy server recognizes that request was to some dynamic content and bypasses request to legacy container (like SAP Net Weaver);
  3. Legacy container returns response to proxy server as if it was accessed directly from browser;
  4. Proxy server returns response to browser as if it was returned directly from application;
  5. Instead of accessing local web server, browser accesses proxy server (to get something static like style.css or script.js);
  6. Proxy server recognizes that request was to some static resource and bypasses request to local web server;
  7. Local web server returns response to proxy server as if it was accessed directly from browser;
  8. Proxy server returns response to browser as if it was returned directly from application;

Note: proxy and remote server are not necessary different server instances, they may be on the same web server, just perform different parts of the job. In such case proxy request may be performed not via HTTP, but as an internal redirect inside the same web server.

For developer as end-user the flow should stay transparent. The only change is that original web application is accessed using different URL. For legacy web container and application deployed on it the flow stays transparent as well, as far as it even doesn’t know that the request was from different place and using different URL (proxy server replaces is own URL with original web application URL when bypasses request to legacy web container). Thus the flow is consistent and does not differ from regular flow when end-user accesses web application directly.

Proxy Server

There are a lot of implementations of proxy server, but I personally prefer to work with Apache httpd server. It is relatively small and simple to use, it may be deployed almost on every platform and it supports many additional modules. Binaries may be downloaded from http://httpd.apache.org/download.cgi. For Windows users installing Apache httpd is as simple as just download it and follow the installation steps for typical installation. Mac users may enjoy preinstalled Apache httpd server (just enable web sharing in system preferencies). Once it is installed and running (by default it starts automatically as a service) you can configure it to work as a proxy server. In order to do so the httpd.conf file should be updated as follows:

  • Uncomment the following lines (remove #):

     LoadModule proxy_module modules/mod_proxy.so

     LoadModule proxy_http_module modules/mod_proxy_http.so

  • Append the file with following configuration, save it and restart Apache Server

     ProxyRequests off

     <Proxy *>

           Order deny,allow

           Allow from all

     </Proxy>

     ProxyPass /<app_name>/<static_folder>/ http://<your_local_ip>/<app_name>/<static_folder>/

     ProxyPass / http://<legacy_web_container_ip_and_port>/

     ProxyPassReverse / http://<legacy_web_container_ip_and_port>/

Note: for Windows users httpd.conf is located somewhere like:

C:\Program Files (x86)\Apache Software Foundation\Apache2.2\conf\httpd.conf

Replace all placeholders with actual names, paths and IPs. If proxy is configured correctly it is possible to access proxy server as original application and receive dynamic content. For example if only CSS folder is configured as static folder, than it will be possible to see all the pages, but without any styling (since local server is not configured yet). By performing this step all steps of the flow except #7 are enabled.

Local Server

Apache httpd server may be used as local web server as well. It should be installed on the machine where the static resources are edited and configured to respond using these static resources. In order to do so the httpd.conf file section <IfModule alias_module> should be updated as follows:

<IfModule alias_module>

Alias /<app_name>/<static_folder> "<path_to_static_folder>/<static_folder>"

<Directory "<path_to_static_folder>/<static_folder>">

      Order allow,deny

      Allow from all   

</Directory>

</IfModule>

Replace all placeholders with actual names, paths and IPs. This step enables #7 from the flow. Since it is done the whole flow should work and it is possible to access application via proxy server URL.

On The Fly Merges And LESS to CSS Compilation

Another problem that developer may deal with is that most modern web applications are optimizing the text based static resources and perform some preprocessing on them before they are delivered. For example Java Scripts used on the same page may be merged into single Java Script file in order to avoid multiple round-trips and adjust the performance; LESS files may be used for styling and processed with LESS compiler in order to generate CSS files at the build time. Since all these optimizations are done, browser is no longer work with original source files of static resources, but with optimized resources. However, developer is still working with source files and wants someone to perform these optimizations on the fly. This is still possible using the environment described before, but with several adjustments.

PHP

First thing that is needed is some scripting language that will allow performing manipulations with files located in the file system. I personally prefer PHP, because of its simplicity and integration with Apache httpd. The examples of the sections below will be provided using PHP. In order to enable PHP in Apache on Windows the following things should be done:

  • Download PHP and install it using typical installation. Binaries may be downloaded from http://php.net/downloads.php
  • Update operational system environment variables list with something like:
    • PATH => C:\Program Files (x86)\PHP\
    • PHPRC => C:\Program Files (x86)\PHP\
  • Update Apache configuration file httpd.conf with the following lines (check that they are not already exist, because some PHP installers add them automatically):

     LoadModule php5_module "C:/Program Files (x86)/PHP/php5apache2_2.dll"

     AddType application/x-httpd-php .php

     PHPIniDir "C:/Program Files (x86)/PHP"

  • Restart Apache server.

In order to check PHP is working, create index.php file in the local web server documents root (on Windows it is something like “C:\Program Files (x86)\Apache Software Foundation\Apache2.2\htdocs\”) and place the following lines:

<?php

phpinfo();

?>

If there were other files in the document root, they may be removed. Now when local server will be accessed (http://localhost/index.php), it will display page that looks like that:

Now when PHP is installed and Apache httpd is configured let us see how it may be useful.

Merging Files

Since PHP has an access to the file system it may be used to merge files on the fly. This is useful when in design time there are several Java Script files that are merged to during the build and loaded as single file by client-side at runtime. In order to achieve this goal proxy server should be configured to pass some requests to relevant PHP scripts instead of static resources. Besides of it there should be the PHP script that performs the merge.

Open Apache httpd configuration file (httpd.conf) of proxy server and insert the following line before the first ProxyPass entry.

ProxyPass /<app_name>/<static_folder>/<merged_file>.js http://<your_local_ip>/<merged_file>.php

Note: the order is important since it defines the priority and the first match will take effect.

Replace placeholders with actual data and place merging PHP script into document root of the local web server.  The example of the script may be seen below (don’t forget to replace placeholders with actual data).

<?php

      ini_set("include_path", "<static_folder_path>;".ini_get("include_path"));

      $scripts = array( "<script_1>.js", "<script_2>.js");

      header("Content-type: application/javascript");

      foreach( $scripts as $script ) {

            include $script;

            echo "\r\n";

      }

?>

Note: if there are several merged files the configuration and merging script should be cloned since each merged file contains different list of resources it is merging.

After this step is done it will be possible to access proxy server with path to merged file and receive it as output of relevant merging PHP script on local web server. This allows the developer to continue working on separate files an leverage them as a single compressed one. The changes taking effect on the fly.

LESS Compilation

Compilation of LESS files to CSS may be performed using PHP as well. The Rewrite module of Apache httpd will be utilized to make the process more generic. The following actions should be performed with local web server:

  • Open http.conf and uncomment the following line:

LoadModule rewrite_module modules/mod_rewrite.so

  • Append configuration file with the following lines:

<IfModule rewrite_module>

RewriteEngine on

RewriteRule ^/<app_name>/<static_folder>/(.*).css /less.php?p=%{REQUEST_URI} [NE]

</IfModule>

  • Restart Apache httpd server;
  • Download PHP version of LESS compiler (from http://leafo.net/lessphp/) and place lessc.inc.php to the document root.
  • Ceate less.php file in the document root and fill it with the following script:

require 'lessc.inc.php';

header("Content-type: text/css");

try {

      if( $_GET["p"] != null ) {

     

            // Convert query parameters to path and file name

            $fullLessFileName = preg_replace(

                  array("@^/<app_name>/@","@/<css_folder>/(.*).css$@"),

                  array("<path_to_app_in_file_system>","/<less_folder>/$1.less"),

                  $_GET["p"]

            );

            $matches = array();

            echo "/*" . $_GET["p"] . "*/\n";

            preg_match("@/<css_folder>/(.*).css@", $_GET["p"], $matches);

            $shortLessFileName = $matches[2];

            // Create temporary directory

            $tmpDir = sys_get_temp_dir() . uniqid();

            exec("mkdir ".$tmpDir);

           

            // Copy LESS files to temporary directory

            copy("<include_files_path>", $tmpDir."/<include_file_name>.less");

            copy( $fullLessFileName, $tmpDir . "/" . $shortLessFileName . ".less");

            // Complile LESS and write CSS to output stream

            $less = new lessc( $tmpDir . "/" . $shortLessFileName . ".less" );

            echo $less->parse();

            // Remove temporary files

            exec("rd /s /q ".$tmpDir);

     

      }

     

} catch (exception $e) {

      echo $e->getMessage();

}

Note: provided script is just an example that may be easily modified to working code (don’t forget to replace placeholders with actual data).

When everything is done it will be possible to access proxy server with path to CSS file and receive it as output of compilation script located on local web server. This allows the developer to continue working with LESS files and don’t worry about compilation.

Summary

It took me about half a day to configure the environment at the first day, but I’m enjoying the benefits of it every day, because it saves up to 80% of time that was spent for redundant compilation and deployment and I can access the application from my mobile device that will load static resources directly from my IDE. Recently I need to modify configuration to add another one application I’m working on, but these are minor changes that follow the same pattern.

Develop with pleasure!