Technical Articles
Utilize ui5-tooling’s extension capabilities for an improved development experience
Before ui5-tooling
entered the stage, the UI5-verse had baked many handcrafted solutions for allowing local UI5 development. There were (and still are!) many shades of skillful tool combinations, from grunt
to gulp
to node
-scripts, that served resources, proxied requests and generated sources.
But all of them shared the same challenge: none were officially released, maintained or supported by SAP, nor by the UI5-team. ui5-tooling
changed that: a toolkit, released and maintained by the UI5 team, positioned to be the go-to instrument for local UI5 development.
In addition to this unified development approach, it immediately brought the UI5 developer community two major benefits:
ui5 serve
the local UI5 application with locally installed UI5 sources (vianpm
)ui5 build
the local UI5 application, for- generating the infamous
Component-preload.js
- building a UI5 application bundled with its’ UI5 resources, for stand-alone usage scenarios and maximum performance
- generating the infamous
Forward to July 2019, when this commit set ground for the topic this blog post is about: extend ui5-tooling with custom tasks and custom server-middleware.
set the stage
So Peter Müßig and me sat together one afternoon (yeah, beverages were involved) and started putting together an example showcase. It consist of a small UI5 application, whose development time is boosted via several custom middleware extension, along with one custom task. All extensions are available as npm
modules for reuse or in git
as a template to create own middlewares and tasks.
All you need to do is run yarn dev
and off it goes:
Talk is cheap, show me the code:
- Example showcase at https://github.com/petermuessig/ui5-ecosystem-showcase
npm
module searches:
middlewares via https://www.npmjs.com/search?q=ui5-middleware ,
task via https://www.npmjs.com/search?q=ui5-task
available custom modules
For reference, here’s what’s available as of publishing this blog post:
ui5-middleware-cfdestination
: reuse destinations set up in SAP CP Cloud Foundry for local proxyingui5-middleware-livereload
: automatic stateful reload of UI5 application when source files changeui5-middleware-livetranspile
: transparent transpilation ofES6
+ JS sources duringui5 serve
ui5-middleware-simpleproxy
: simple proxy for remote systems, fulfilling browser runtime CORS policyui5-task-transpile
: transpileES6
+ JS sources forui5 build
use npm
modules for middleware and tasks
The extension concept of ui5-server
can be used with npm
: install a module, then configure it for use with ui5 serve
.
Here’s how, for an existing UI5 application:
init the app for use with ui5-tooling
As described in the UI5 Tooling – Getting Started:
$> npm install --global @ui5/cli # install ui5-tooling globally
$> npm install --global yarn # we're using yarn over npm in the showcase
$> cd app
$/app> npm init --yes # generate a package.json
$/app> ui5 init # generate ui5.yaml
$/app> npm install @openui5/sap.ui.core, ... # install ui5 libs
install and configure middleware extension
Installation is “as usual” via npm
(or yarn
):
$/app> npm install ui5-middleware-livereload --save-dev # custom middleware extension, yay!
Configuration is two-fold:
- in your app’s
package.json
- in your app’s
ui5.yaml
// package.json
{
// ...
"ui5": {
"dependencies": [
"ui5-middleware-livereload"
]
}
}
// ui5.yaml
// ...
server:
customMiddleware:
- name: ui5-middleware-livereload
afterMiddleware: compression
configuration:
debug: true
port: 35729
path: webapp
That’s it!
Once you run ui5 serve
in your /app
directory, you should see the middleware light up in your console:
info middleware:custom:livereload Livereload connecting to port 35729 for path webapp
Watching /path/to/app/webapp...
info middleware:custom:livereload Livereload server started...
Server started
Subsequently, any changes to a js
-file (or css
, html
, xml
, properties
, …) will trigger a live reload of the app – in all (!) browsers having the app open. See the documentation of ui5-middleware-livereload
for further information on the middleware.
The above install- and config-approach holds true for all middleware/tasks of the ui5-ecosystem showcase. See the included example app configuration (ui5.yaml
) for a comprehensive example.
what is this magic?
aka: “how to roll your own middleware/task” 🙂
implementation
For developing a custom middleware or task, the extension needs to implement a certain function
signature, whether it’s a middleware or a task:
/**
* Custom UI5 Server middleware example
*
* @param {Object} parameters Parameters
* @param {Object} parameters.resources Resource collections
* @param {module:@ui5/fs.AbstractReader} parameters.resources.all Reader or Collection to read resources of the root project and its dependencies
* @param {module:@ui5/fs.AbstractReader} parameters.resources.rootProject Reader or Collection to read resources of the project the server is started in
* @param {module:@ui5/fs.AbstractReader} parameters.resources.dependencies Reader or Collection to read resources of the projects dependencies
* @param {Object} parameters.options Options
* @param {string} [parameters.options.configuration] Custom server middleware configuration if given in ui5.yaml
* @returns {function} Middleware function to use
*/
module.exports = function({resources, options}) {
return (req, res, next) => {
// [...]
}
};
For the middleware, the function
signature is connect– and express-compatible. So all middleware suitable for those two frameworks are in principal compatible to ui5-server
as well!
file system structure, configuration
The implementation js
-file(s) need to go into a folder with a dedicated name, containing several mandatory files. Take ui5-middleware-livereload
as an example:
ui5-middleware-livereload
├── README.md
├── lib
│ └── livereload.js
├── node_modules
├── package.json
└── ui5.yaml
ui5.yaml
describes the extension and is self-explanatory:specVersion: '1.0' metadata: name: ui5-middleware-livereload kind: extension type: server-middleware middleware: path: lib/livereload.js
package.json
is annpm
-standard like file for describing the package
Yep, you guessed it: looking at the latter, this fulfills the requirement of publishing the UI5 server extension as a publicly available npm
module.
For re-use.
By the entire UI5-verse of developers.
Which brings us to…
what next?
You guys: Go code.
Lots of ui5-tooling
extensions, be it tasks or middlewares.
Publish them on npm
. Follow the naming convention ui5-{middleware|task}-{name}
.
So other UI5 developers can re-use them. And you can re-use others’ extensions.
That as a the UI5 development community, we can work better, more efficient, grow in skill and knowledge – and have some fun while doing it! Help us and build #endlesspossibilities for #UI5
Will this work with sapui5? Reading the UI5 tooling doco it seems it’s only for openui5.
top of my head: only the selfcontained build of ui5-tooling will only work with OpenUI5.
However, the custom transpile
build
-task and middlewares are library-agnostic and work with both UI5 flavors, SAP- and OpenUI5. I’ve already used all of the above middlewares in another project with a SAPUI5-bootstrap.If only SAPUI5 would rather sooner than later dissolve into OpenUI5. Sigh.
This is quite amazing. I am bit surprised that it not part of the cli core project. This allows a developer to easily hack/extend the core and so make the cli usable in real life.
I already rewrote your ui5-middleware-simpleproxy module so that it becomes possible to proxy oData requests to a backend system, something that is surprisingly not even part of the core...
I also feel the need for a task used in the build process. I started writing libraries, published them as npm in a private registry and consumed them in another project. Now, I try to build my project, embedding my modules in the dist but not the ui5 core libraries. The standard build task does not allow me to do this. But seems a far more challenging 'task'...
This is a great resource. Thanks Volker!
I've created a copy of the SimpleProxy middleware with basic authentication.
Should anyone want to use it too, you can find it at https://www.npmjs.com/package/ui5-middleware-proxy-basicauth.
supercool!
now if you were to use "passport" or similar to bolt-in sap id/saml2 and/or openid, now that would even be supercooler! 🙂
Hi Volker,
nice blog.
I am using the ui5-middleware-cfdestination but want to access an on-premise system through SAP CF! Also the current approach does not support saml, etc.
Do you have a proxy solution to tunnel the local destination through sap cf including saml authentication?
Regards Holger
Hi Holger,
can’t help here, sorry – no saml support in the middleware.
but you should be able to connect to an on-prem system via
ui5-middleware-cfdestination
:disclaimer: all top of my head, untested
hope that at least gets you in the right direction,
best, v.