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: 
nicoschoenteich
Developer Advocate
Developer Advocate
In this SAP Tech Byte I will describe how to run a UI5 app with an express server and deploy it to the Cloud Foundry environment. You might wonder why one should use express to serve a UI5 app instead of using the UI5 Tooling (e.g. running "ui5 serve", which also runs express under the hood by the way). One reason for this might be that you want to handle more endpoints within your app and execute something server-side, e.g. a file upload. We recently came across this situation in the SAP Community Code Challenge, which inspired me to write this blog post.

 

Initializing the UI5 app


A great tool for scaffolding UI5 apps is the easy-ui5 generator. Let's open a terminal and install it globally so we have it set up for future occasions as well:
npm install -g yo generator-easy-ui5

After installing it, we can initialize our project:
yo easy-ui5 project

In the dialog you want to make the following selections (you can choose a different name for your project, of course):



Open the newly created directory in your favourite editor.

 

Setting up the express server


First, we want to install express and another package called dotenv, which we will need later:
npm install express dotenv

Now we can create a new index.js at root level of our project and insert the following code:
const express = require("express");
const path = require("path");
const app = express();

app.use("/", express.static(path.join(__dirname, "./uimodule/webapp")));

const port = process.env.PORT || 8000;
app.listen(port, () => console.log(`Server started at http://localhost:${port}`));

This spins up an express server and statically serves the files in uimodule/webapp for incoming reguests.

The new start command for our app is node index.js.

Because the Cloud Foundry environment always wants to start node.js apps with the command npm start (and also because it's good practice), let's replace the current start script in our package.json with our new start command:
...
"scripts": {
"start": "node index.js",
...
}
...

This leaves us with a problem. You might have noticed that we just deleted the ui5 serve command, which picks up the configuration defined in the ui5.yaml file, such as which framework and libraries we use. This means the index.html in our UI5 app will now have to work "standalone". In order to achieve that, we have to modify the bootstrapping of our app. In our index.html, we insert the link to the sap-ui-core CDN, instead of linking to local resources:
<script
id="sap-ui-bootstrap"
src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js"
...
</script>

We can now start our app:
npm start

Our app should now be reachable at http://localhost:8000:



 

 

Preparing the deployment to Cloud Foundry


Before pushing our app to Cloud Foundry, we want to build it. Let's do that now:
npm run build:ui

The build created a new folder uimodule/dist as it is specified in the build:ui script in our package.json. In our index.js we have told our express server to statically serve all files inside the uimodule/webapp folder for incoming requests. But after the build and running in the cloud, we want to serve the files from uimodule/dist. This means our express server needs to know whether it is running in development or not and needs to behave differently based on that condition. This is where the dotenv package comes into play, which we installed in the beginning. The dotenv package picks up whatever we put in a .env file. So let's create this file and insert the following code.
NODE_ENV="development"

We have now hardcoded the node environment to be "development". In order to not push this information to Cloud Foundry, we create yet another file, called .cfignore. In there, we list all the files and folders we don't want to deploy:
.env
uimodule/webapp/ #not needed, as we have our build result in uimodule/dist/
node_modules/ #cloud foundry will run another npm install for us

Now we can go into our index.js file and import the dotenv package as well as insert the condition that checks for the node environment the express server is running in:
const express = require("express");
require("dotenv").config();
const path = require("path");

const app = express();
app.use(express.json());

if (process.env.NODE_ENV === "development") {
console.log("Running in development...");
app.use("/", express.static(path.join(__dirname, "./uimodule/webapp")));
} else {
app.use("/", express.static(path.join(__dirname, "./uimodule/dist")));
}

app.get("/another-endpoint", function(req, res) {
res.send({
message: "Hi there!"
});
});

const port = process.env.PORT || 8000;
app.listen(port, () => console.log(`Server started at http://localhost:${port}`));

During development the dotenv package will pick up the .env file and set the NODE_ENV to development. In this case the folder uimodule/webapp will be served. But running in Cloud Foundry, the .env won't exist and therefore the NODE_ENV will be undefined. In that case the uimodule/dist will be served.

Notice how we also made our express server capable of handling JSON (line 6) and how we added /another-endpoint to our backend. Feel free to execute whatever piece of code you wish inside this function. Simply call "/another-endpoint" from within your app and let the express server do the work.

 

Deploying to Cloud Foundry


We want to deploy our app to Cloud Foundry using the convenient cf push command. For that, we need a manifest.yaml file on root level of our project with minimal deployment configuration:
---
applications:
- name: ui5express
buildpacks:
- nodejs_buildpack
memory: 512M

After the deployment is finished, we should see our app successfully running in the cloud (you can find the URL in the logs of the deployment):



 

Trying it yourself


There’s a branch for this SAP Tech Bytes post in the accompanying SAP Tech Bytes repository: Check it out and follow the instructions here:

https://github.com/SAP-samples/sap-tech-bytes/tree/2022-02-18-ui5-express-cf


SAP Tech Bytes is an initiative to bring you bite-sized information on all manner of topics, in video and written format. Enjoy!