ui5-middleware-hmr
An experimental UI5 middleware for hot module replacement, swapping a changed module in during development instead of reloading the whole page.
Replaces the UI5 dev server's full-page live reload with hot module replacement, so a changed module can be swapped in without reloading the whole page. The package labels itself experimental, and its registry page carries no README beyond the one-line description.
Facts
Where it sits
Who is behind it
In the atlas: maintains 69@ui5-communitymaintainerPeter MuessigContributes to this
In the atlas: maintains 14, contributes to 80, wrote 1@petermuessig1 contributor
What it declares
Every artifact
- Type
- Build tool
- Origin
- By a community org
As a build tool
- Distributed through
- npm
Connections
Serving an app locally and building it for deployment
Download
Install
npm add ui5-middleware-hmrDerived from the package name. No recipe recorded; the README has the configuration.
README
quoted from ui5-community/ui5-ecosystem-showcase under Apache-2.0, readUI5 middleware for hot module replacement (HMR) of webapp sources on change — EXPERIMENTAL
👋 This is an open‑source, community‑driven project, developed and actively monitored by members of the UI5 community. You are welcome to use it, report issues, contribute enhancements, and support others in the community.
Middleware for ui5-server, doing a hot module replacement when files inside $yourapp change, e.g. on save — reloading only what changed instead of the whole page.
⚠️ Experimental prototype. This middleware attempts true hot module replacement for UI5 apps instead of a full-page live reload. It relies on a private, deprecated UI5 loader API and internal control/registry behavior. It is intended for local development only and may break across UI5 versions. When the mechanism is unavailable it degrades to a full page reload.
What gets hot-swapped vs. reloaded:
| Change | Behavior |
|---|---|
*.css | stylesheet re-injected, no reload |
*.js / *.ts leaf module (formatter, model, helper) | module unloaded + re-required |
*.js / *.ts leaf with dependents | changed module and its transitive dependents unloaded + re-required (server computes the dependency graph) |
*.controller.js | owning view(s) re-instantiated in place; models preserved |
*.properties (i18n) | ResourceModel recreated with a cache-busted bundle + swapped onto the component; bound texts refresh, no reload |
*.json | matching JSONModel reloaded via loadData (cache-busted) |
*.view.xml (non-routed) | owning XMLView(s) re-instantiated in place (template re-read fresh); models preserved |
*.view.xml (routed target) | router re-matches the current route and rebuilds the view through its own lifecycle; models preserved |
*.view.js / *.view.ts (TypedView or classic JSView) | changed view module re-required + owning view(s) re-instantiated in place; models preserved |
*.view.xml (root view / sap.ui5/rootView) | owning Component rebuilt in place (see Component.js) |
*.fragment.xml (embedded in a view) | embedding view(s) re-instantiated (server resolves fragment → views); models preserved |
Component.js / Component.ts | Component rebuilt in place through its ComponentContainer; current route preserved; runtime model state lost |
*.fragment.xml (loaded imperatively, e.g. dialogs) | full reload (no embedding view to re-instantiate) |
*.xml (other) | full reload |
| anything else | full reload |
See Scenarios: what improves over live reload for the full matrix with the reasoning behind each case.
Prerequisites
- Requires at least
@ui5/cli@3.0.0(to supportspecVersion: "3.0")
⚠️ UI5 CLI Compatibility All releases of this UI5 CLI extension using the major version
3require UI5 CLI V3. Any previous releases below major version3(if available) also support older versions of the UI5 CLI. But the usage of the latest UI5 CLI is strongly recommended!
Install
npm install ui5-middleware-hmr --save-dev
Configuration options (in $yourapp/ui5.yaml)
- debug: true|false verbose logging (server + browser console)
- port:
integer, default: an free port choosen from35739onwards port the hot module replacement (WebSocket) server is started on - watchPath|path:
string, default: all paths from app and non framework dependencies path inside$yourappthe server monitors for changes - exclusions: one or many
regex. By default, this includes.git/,.svn/, and.hg/ - usePolling: true|false, default:
falseEnables chokidar polling to support virtualised filesystems(eg. WSL2.0). - force: true|false, default: unset
force-enable (
true) or force-disable (false) the middleware, overriding the automatic UI5 Tooling V5+ auto-disable (see UI5 Tooling V5 below)
UI5 Tooling V5
UI5 Tooling V5 provides a built-in Live Reload. Per the official docs, combining a custom live-reload middleware with the built-in feature can make the page "refresh more often than necessary." To avoid that, this middleware automatically disables itself when running under UI5 Tooling V5 or higher (detected via the @ui5/server major version).
- To keep using this middleware under V5, set
configuration.force: trueand disable the built-in Live Reload via the--no-live-reloadCLI flag or theserver.settings.liveReloadconfiguration option (otherwise both run and the page double-reloads). - To disable this middleware on any tooling version, set
configuration.force: false.
See the UI5 CLI v5 migration guide for details on the built-in Live Reload and other V5 changes.
Usage
- Define the dependency in
$yourapp/package.json:
"devDependencies": {
// ...
"ui5-middleware-hmr": "*"
// ...
}
- configure it in
$yourapp/ui5.yaml(use instead ofui5-middleware-livereload):
server:
customMiddleware:
- name: ui5-middleware-hmr
afterMiddleware: compression
Using the configuration properties (if needed):
server:
customMiddleware:
- name: ui5-middleware-hmr
afterMiddleware: compression
configuration:
debug: true
port: 35739
watchPath: "webapp"
or with path instead of watchPath:
server:
customMiddleware:
- name: ui5-middleware-hmr
afterMiddleware: compression
configuration:
debug: true
port: 35739
path: "webapp"
Watch multiple paths:
server:
customMiddleware:
- name: ui5-middleware-hmr
afterMiddleware: compression
configuration:
debug: true
port: 35739
path:
- "webapp"
- "../my.reuse.library/src/my/reuse/library"
Use polling to watch files:
server:
customMiddleware:
- name: ui5-middleware-hmr
afterMiddleware: compression
configuration:
debug: true
port: 35739
usePolling: true
Exclude single subpath from paths/ watchPaths:
server:
customMiddleware:
- name: ui5-middleware-hmr
afterMiddleware: compression
configuration:
debug: true
port: 35739
watchPath: "webapp"
exclusions:
- "wdi5/"
Exclude multiple subpaths from paths/ watchPaths:
server:
customMiddleware:
- name: ui5-middleware-hmr
afterMiddleware: compression
configuration:
debug: true
port: 35739
watchPath: "webapp"
exclusions:
- "wdi5/"
- "integration/"
How it works
-
The server watches source paths with chokidar and classifies each change into a typed event carrying the UI5 module name.
-
Events are pushed to the browser over a WebSocket.
-
A small client runtime (injected before
</body>) dispatches per type. Module hot-swap uses the private loader API:sap.ui.loader._.unloadResources(name + ".js", /*bPreloadGroup*/ false, /*bUnloadAll*/ true, /*bDeleteExports*/ true);which removes the module from the loader registry so the next
sap.ui.requirere-fetches and re-executes fresh code.
When a change cannot be hot-swapped, the middleware falls back to a full reload — so, like a live reload, all connected browsers reload the application, #-aware (the current displayed route in your single-page UI5 app is kept steady).
Why not "real" webpack/Vite-style HMR?
UI5 has no HMR-aware module runtime and no framework hook to rebind a fresh controller onto a live view. unloadResources gives us module-graph invalidation, which makes leaf-module swap and view re-instantiation possible, but it does not give us state-preserving controller swap. So controllers are handled by re-instantiating the owning view (models survive; that view's transient UI state does not).
Scenarios: what improves over live reload
ui5-middleware-livereload does one thing on any change: reload the whole page. That is
robust, but it throws away all application state — the current route, open dialogs, form input,
model data fetched from a backend, scroll position — and pays a full framework boot on every save.
HMR's goal is to apply the smallest change that makes your edit visible while keeping as much live state as possible. The table below is every scenario that was designed and verified, what HMR does, and — crucially — why it works or why it still falls back to a reload.
Legend: 🟢 hot-swap (no reload) · 🟡 partial (in-place rebuild, some transient state lost) · 🔴 full reload (same as live reload).
Styling & assets
| Scenario | HMR | Live reload | Why |
|---|---|---|---|
*.css change | 🟢 stylesheet re-injected | 🔴 reload | The changed <link>'s href is re-pointed with a cache-busting query param. The browser re-parses just that stylesheet; the DOM, route and all app state are untouched. |
Plain modules (formatter / model / helper / util)
| Scenario | HMR | Live reload | Why |
|---|---|---|---|
Leaf *.js/*.ts module with no dependents | 🟢 unloaded + re-required | 🔴 reload | sap.ui.loader._.unloadResources drops the module from the loader registry; the next sap.ui.require re-fetches fresh code. Nothing else references stale code. |
Leaf module with dependents (other app modules sap.ui.define-import it) | 🟢 module + transitive dependents unloaded + re-required | 🔴 reload | A module that already captured the old reference in its closure would keep using it. The server parses sap.ui.define([...]) arrays across the app to compute the reverse-dependency set and tells the client to unload them too, so every holder re-requires fresh code. |
Module whose dependency is only referenced via a computed name or in-body sap.ui.require([...]) | 🟡 changed module swaps, that dependent may not refresh | 🔴 reload | The static graph only sees literal sap.ui.define([...]) arrays (the loader's forward deps are closure-private, so no client-side graph is possible). Dynamically-named deps are invisible to it. Edit the dependent directly to force its refresh. |
Controllers
| Scenario | HMR | Live reload | Why |
|---|---|---|---|
*.controller.js/.ts own-code change | 🟡 owning view(s) re-instantiated in place | 🔴 reload | UI5 has no API to rebind a fresh controller onto a live view. So the client re-requires the controller to a fresh class first, then re-creates the owning XMLView with the same id in the same aggregation slot. Component/parent models survive; the view's transient UI state (scroll, selection, unsaved input) is lost. |
| Controller change where a routed view owns it | 🟡 router re-matches + rebuilds the view | 🔴 reload | Same as above, but routed views are rebuilt through the router (see routed views below) so navigation state stays consistent. |
Views (*.view.xml, *.view.js, *.view.ts)
| Scenario | HMR | Live reload | Why |
|---|---|---|---|
| Non-routed view embedded in a control aggregation | 🟡 re-instantiated in place | 🔴 reload | XMLView.create re-reads the template from the server (no XML cache to bust) and is inserted into the same aggregation slot with the original id. Typed aggregation mutators (e.g. insertPage) are preferred so container bookkeeping (CSS classes, height) is applied. |
| Routed view that is currently displayed | 🟡 router re-match rebuilds it in place | 🔴 reload | The router owns routed views' whole lifecycle (view cache, NavContainer current-page, nav history). The client evicts the router's view cache, destroys the old instance, and calls router.parse(currentHash) so the router rebuilds and re-navigates — with the transition forced to instant show, so the edited view reappears with no root flash / slide. |
Routed view in a subfolder (e.g. view/fiori/DynamicPage.view.xml, target viewName: "fiori.DynamicPage") | 🟢 fixed — router re-match | 🔴 reload | This used to misbehave (see below). The target's viewName is relative to viewPath and contains a dot (fiori.DynamicPage); the fix matches it against both the qualified and the viewPath-relative form, so subfolder targets are recognized and refreshed through the router instead of falling back. |
| Routed view that is not the current page | 🟡 evicted, rebuilt on next navigation | 🔴 reload | Re-parsing the hash would spuriously re-navigate to the current route. Instead the client just evicts the router cache entry; the next real navTo rebuilds it cleanly via a cache miss. |
JS view — TypedView (*.view.js/.ts, View.extend + createContent) or classic JSView (sap.ui.jsview) | 🟡 module re-required + view re-instantiated in place | 🔴 reload | A JS view is a module, so a change is both a code change and a view change. The client unloads + re-requires the module to a fresh class, then re-instantiates the live view(s) through the same path as XML views (aggregation-slot swap or router re-match). The two flavours report getViewName() differently — TypedView keeps the .view module segment, JSView drops it — so the live instance is matched against the changed module with or without its trailing .view. Models on the parent/component survive; transient view UI state is lost. |
Root view (the manifest sap.ui5/rootView, e.g. App.view.xml) | 🟡 owning Component rebuilt in place | 🔴 reload | The root view's parent is the UIComponent itself (no aggregation slot to swap into), so it's refreshed by rebuilding the Component (see below). Route is preserved. |
Components
| Scenario | HMR | Live reload | Why |
|---|---|---|---|
Component.js/.ts change | 🟡 Component rebuilt in place, route preserved | 🔴 reload | This used to be a full reload. The client finds the live component's ComponentContainer, clears the association, destroys the old instance, and lets the declarative container recreate it via its own lifecycle. Component.create({manifest:true}) re-reads a fresh manifest.json, and the new init() re-initialises the router, which re-parses the current hash — so you stay on the same route. Runtime model/app state (backend reads, user input) is lost; that's the cost of rebuilding the app root, still cheaper than a full framework boot. |
| Component change reached only as a dependent of another changed module | 🟡 Component rebuilt | 🔴 reload | Previously a Component appearing in the dependents set was silently dropped. It now rebuilds like a direct change. |
manifest.json change (rootView, routing, models, dependencies) | 🟡 picked up on the next Component rebuild | 🔴 reload | The manifest is re-fetched (no-store) whenever the Component is recreated, so editing the Component (or root view) applies manifest changes too. A standalone manifest-only edit is not yet a dedicated trigger. |
i18n & data
| Scenario | HMR | Live reload | Why |
|---|---|---|---|
*.properties (i18n) change | 🟢 ResourceModel recreated + re-bound | 🔴 reload | ResourceBundle caches parsed properties by URL, so the model is recreated with a cache-busted bundleUrl (a new query key forces a re-parse) and swapped onto the component, which re-resolves i18n bindings. The server sends no-store for .properties so the fetch hits disk. Bound texts update with no reload. |
*.json model change | 🟢 JSONModel.loadData (cache-busted) | 🔴 reload | The matching model (declared in the manifest with a uri/dataSource) is re-loaded via loadData; bindings update automatically. |
Fragments (*.fragment.xml)
| Scenario | HMR | Live reload | Why |
|---|---|---|---|
Fragment embedded declaratively (<core:Fragment fragmentName="…"/>) | 🟡 embedding view(s) re-instantiated | 🔴 reload | A fragment has no live instance of its own, but the server keeps a fragment→view graph (parsed from fragmentName= references, resolved transitively for fragments-in-fragments) and tells the client which view(s) to rebuild; XMLView.create re-reads the fragment fresh. |
Fragment loaded imperatively (Fragment.load(...), typically dialogs) | 🔴 full reload | 🔴 reload | There is no embedding view to re-instantiate and no live handle to the fragment's content, so there's nothing to swap in place. Honest reload. |
Fragment referenced by a computed fragmentName | 🔴 full reload | 🔴 reload | Only static fragmentName attributes are parsed into the graph; a computed name can't be resolved to a view, so it reloads. |
Bootstrap & everything else
| Scenario | HMR | Live reload | Why |
|---|---|---|---|
Other *.xml, *.view.json, *.view.html / unknown file types | 🔴 full reload | 🔴 reload | No safe in-place strategy. JSON/HTML views are not covered (only XML and JS views are); everything unrecognized degrades to reload. |
Private loader API (unloadResources) unavailable (removed in a future UI5) | 🔴 full reload | 🔴 reload | Feature-detected at connect time; if missing, all module/view/component changes fall back to reload, so HMR degrades to live-reload behavior rather than breaking. |
| Nested app / running behind a path-prefixing proxy | 🟢 client script still loads | n/a | The injected client <script src> is relative to the served HTML (not server-root-absolute), so it resolves back to this server's root at any nesting depth. |
Notes on two bugs that were found & fixed here
Both were in the routed-view path and produced the classic "I edited a nested view and it jumped back to the first page" symptom:
- Subfolder routed targets never matched. The target-name matcher assumed a dotted
viewNamewas already fully-qualified — but a relative name in a subfolder (fiori.DynamicPage) also contains a dot. Such targets silently dropped to the generic aggregation swap. Fixed by matching against both the qualified and theviewPath-relative interpretation. - Routed views could misroute into a Component rebuild. A routed target view can transiently
report an empty
getParent(); the "is this a root view?" check misread that as the Component's root view and rebuilt the whole Component → full reload landing on the default (first) page. Fixed by attempting the router-based swap first, so a routed target is always handled by the router.
Known limitations
- Private + deprecated API.
sap.ui.loader._.unloadResourcesis private and deprecated as of UI5 1.135 ("without replacement"). Feature-detected; falls back to full reload when missing. - Reverse-dependency tracking is static + server-side. The dependency graph is built
by parsing
sap.ui.define([...])arrays across the app's own modules (the loader's forward deps are closure-private, so a client-side graph isn't possible). Computed dependency arrays orsap.ui.require([...])inside function bodies are not tracked. - Controller hot-swap re-instantiates the owning view. On a controller change (or a
change to a leaf it depends on), the client re-requires the controller module to a fresh,
executed class before calling
XMLView.create, then swaps the new view into the same aggregation slot with the original id preserved. Doing the re-require explicitly (rather than lettingcreatetrigger it) avoids a race where the view would instantiate a stale controller class. Verified for controller-own-code changes, leaf-dependency propagation, and repeated consecutive edits. The view's transient UI state (scroll, selection) is lost; models on the component/parent survive. - JS view (
*.view.js/.ts) hot-swap covers both a modern TypedView (sap.ui.core.mvc.View.extend()withcreateContent) and a classic JSView (sap.ui.jsview(...), deprecated). Because a JS view is itself a module, the change is both a code change and a view change: the client unloads + re-requires the module to a fresh class, then re-instantiates the live view(s) through the same machinery as XML views (in-place aggregation swap for embedded views, router re-match for routed targets). A JSView is created withView.create({type:"JS"})and a TypedView withView.create({viewName:"module:…"}); the live instance is matched against the changed module with or without its trailing.viewsegment, since the two flavours reportgetViewName()differently. Transient view UI state is lost; component/parent models survive. JSON views (*.view.json) and HTML views (*.view.html) are not covered and fall back to a full reload. - XML view (
*.view.xml) hot-swap re-instantiates the matching liveXMLView(s):XMLView.createre-reads the template from the server (no XML cache to bust), so the new markup renders in place with the original view id preserved. For routed views, the router owns the view lifecycle: the client evicts the router's view cache, destroys the old instance, and re-matches the current route (router.parse(hash)) so the router rebuilds and re-navigates cleanly — using an instant transition so the edited view reappears in place (no root flash / slide). Same trade-off as controller swap — transient view UI state is lost, component/parent models survive. - Component (
Component.js) and root-view hot-swap rebuild the Component in place. The client resolves the live component'sComponentContainer, clears the association, destroys the old instance, and lets the (declarative) container recreate it through its own lifecycle.Component.create({manifest:true})re-reads a freshmanifest.json, and the newinit()re-initialises the router, which re-parses the current hash — so the active route is preserved. The container's storedsettings.idis normalized before recreation becauseComponentContainer._createComponentmutates it in place (prefixing with the container id), which is not idempotent and would otherwise double-prefix the id on repeated swaps. Because the whole control tree is rebuilt, runtime model/app state is lost (heavier than a view swap, still lighter than a framework boot). The manifestrootViewis refreshed the same way (its parent is theUIComponent, so there is no aggregation slot to swap into). Any failure in this path degrades to a full reload. - Fragments (
*.fragment.xml): embedded ones hot-swap, imperative ones reload. A fragment has no live instance of its own, but a fragment embedded declaratively in a view (<core:Fragment fragmentName="…"/>) is re-read fresh when that view is re-instantiated. The server keeps a fragment→view graph (parsed fromfragmentName=references across*.view.xml/*.fragment.xml, resolved transitively for fragments-in-fragments) and, on a fragment change, tells the client which view(s) to re-instantiate. Fragments loaded imperatively in a controller (Fragment.load(...), typically dialogs) have no embedding view, so they fall back to a full reload. Only staticfragmentNameattributes are tracked (computed names are not). - Timing. The server waits for writes to settle (
awaitWriteFinish) and sendsCache-Control: no-storefor app.js/.properties/.json/.xml(not framework/resources/), and the client pre-fetches a module's canonical URLno-storebefore re-requiring — together these prevent a hot-swap from loading stale bytes. - i18n (
.properties) hot-refresh recreates eachResourceModelfrom its manifest config with a cache-bustedbundleUrland swaps it onto the owning component, which re-resolves the i18n bindings. Two details make it work:ResourceBundlecaches parsed properties by URL (so a new query param is required to force a re-parse), and the middleware sendsCache-Control: no-storefor.properties/.json(so the fetch hits disk, not the browser cache). Reusing the same URL — viabundleNameor_handleLocalizationChange— returns the stale bundle. - JSON hot-reload uses
JSONModel.loadData(uri)with a cache-busting query param. TheloadDatamechanism is verified; end-to-end matching relies on the model being declared in the manifest with auri(or a referenceddataSource). - WebSocket runs on its own port (default from
35739), separate from the UI5 server.
Misc/FAQ
yep, cross-browser, cross-platform.
License
This work is licensed under Apache 2.0.
Built with care (and a lot of caffeine). If this helped you build, test, or ship, the next coffee — or drink — is on you when you bump into a contributor.
History
Features 1
Notes
Minor Changes
-
#1422
1411b16Thanks @petermuessig! - feat(ui5-middleware-hmr): first feature release of the experimental HMR middlewareui5-middleware-hmrperforms hot module replacement ofwebappsources on change instead of a full-page live reload — reloading only what changed while preserving as much application state (route, models, open dialogs) as possible.Highlights:
- CSS, i18n (
.properties) and JSON model hot-refresh with no reload - leaf module + transitive dependent unload/re-require (static dependency graph)
- controller changes re-instantiate the owning view(s) in place
- XML views and JS views (TypedView and classic JSView) hot-swap in place; routed targets are refreshed through the router with the active route preserved
- Component / root-view changes rebuild the Component in place
- resilient lifecycle: the websocket server and file watcher are torn down on
process exit, a websocket error no longer crashes the dev server, invalid
exclusionspatterns are skipped with a warning, and the page reloads once on reconnect after a dev-server restart - honest full-reload fallback whenever an in-place strategy isn't available
Experimental: relies on the private, deprecated
sap.ui.loader._.unloadResourcesAPI and internal control/registry behavior. Intended for local development only and may break across UI5 versions; it feature-detects the API and degrades to a full reload when unavailable. JSON and HTML views are not covered and full-reload. - CSS, i18n (
Fixes 1
Notes
Patch Changes
-
#1420
d9100faThanks @petermuessig! - chore(ui5-middleware-hmr): bootstrap initial publish (0.0.1)Initial bootstrap release to establish the
ui5-middleware-hmrpackage on the npm registry so that npm OIDC trusted publishing can be configured for it (the very first publish of a new package name cannot use OIDC). The feature-complete0.1.0release follows once trusted publishing is set up.ui5-middleware-hmris an experimental UI5 CLI server middleware that performs hot module replacement ofwebappsources on change instead of a full-page live reload. See the README for the full behavior matrix and caveats.
-
Others providing
Compare all 42 on the Build and dev-server tooling page →- UI5 ToolsUI5 ToolsA VS Code extension for UI5 developers that serves, proxies, builds and deploys UI5 projects from one workspace-wide configuration, with live reload, a Gateway deployer and a BSP importer.independent, ui5VS Code extension to serve, proxy, build and deploy UI5 projects
- ui5-middleware-route-proxyui5-middleware-route-proxyA UI5 server middleware that forwards requests matching a route prefix to a backend host, configured per route in ui5.yaml, with credentials read from a .env file rather than the yaml.independent, ui5UI5 server middleware proxying route prefixes to a backend
- ui5-task-cachebuster-indexingui5-task-cachebuster-indexingA UI5 builder task that copies the build output into a timestamped folder inside dist so the UI5 cachebuster can resolve it; it supports timestamps only, not the hash mode.independent, ui5UI5 builder task preparing build output for the cachebuster
- ui5-task-transpile-genui5-task-transpile-genA UI5 builder task that transpiles ES6 to ES5, including async/await, with Babel at build time, registered in ui5.yaml with a bundle definition that includes the regenerator runtime.independent, ui5UI5 builder task transpiling ES6 to ES5 with Babel
- ui5-middleware-odata-recorderui5-middleware-odata-recorderA UI5 server middleware that records the OData traffic a running app makes against a real backend and writes entity JSON files and metadata.xml that the Fiori elements mock server can replay.independent, ui5UI5 middleware recording OData traffic as mock server datasets
- ui5-plugin-loaderui5-plugin-loaderA UI5 Tooling v4 extension that registers a project's other extensions itself: one entry in ui5.yaml, and every dependency carrying a ui5-plugin-loader.json manifest is mounted as middleware and as a build task.independent, ui5UI5 Tooling v4 extension that registers other extensions
- ui5-deployerui5-deployerA custom module for UI5 Tooling that deploys Fiori/UI5 apps to SAP NetWeaver ABAP, SAP Cloud Platform Neo or Cloud Foundry, configured in a deployer section of ui5.yaml.independent, ui5UI5 Tooling module deploying Fiori/UI5 apps to SAP systems
- ui5-task-dts-generatorui5-task-dts-generatorA UI5 builder task that generates d.ts files, TypeScript type declarations, during the build of a UI5 library written in JavaScript, by wrapping @ui5/dts-generator.independent, ui5UI5 builder task generating d.ts type declarations
- ui5-task-minifierui5-task-minifierA UI5 builder task that minifies the HTML, CSS and JSON files the UI5 builder leaves as they are, with one switch per file type, using html-minifier-terser and clean-css.independent, ui5UI5 builder task minifying HTML, CSS and JSON files
- ui5-middleware-oidcui5-middleware-oidcA UI5 Tooling server middleware that puts an OpenID Connect login in front of the UI5 dev server, built on express-openid-connect, which receives its configuration block as written.independent, ui5UI5 dev server middleware adding an OpenID Connect login
- generator-ui5-library-af-deploygenerator-ui5-library-af-deployA Yeoman generator that writes the SAP BTP Application Frontend deployment configuration, mta.yaml, ui5-deploy.yaml, xs-app.json and xs-security.json, into an existing UI5 library project.independent, ui5Yeoman generator for Application Frontend config in UI5 libraries
- ui5-middleware-destinationui5-middleware-destinationA UI5 Tooling server middleware that proxies requests to backends named in WebIDE-style destination files and serves the routes of a neo-app.json, with Basic Authentication only.independent, ui5UI5 Tooling middleware proxying destinations and neo-app.json routes
- ui5-task-check-eocpui5-task-check-eocpA UI5 builder task that matches the UI5 version in ui5.yaml against the versions retrieved from ui5.sap.com and warns during the build once that version's End of Cloud Provisioning quarter has been reached.independent, ui5UI5 build task warning when the app's UI5 version reaches EOCP
- @ui5/cli@ui5/cliThe UI5 Tooling command line for project setup, the local dev server and the build, which defines a UI5 project's shape and its two extension points, custom middleware and custom tasks.sap official, ui5UI5 Tooling command line for project setup, dev server and build
- ui5-task-btp-manifestui5-task-btp-manifestA UI5 Tooling custom task that writes the surrounding app's sap.cloud service name into the bundled Spreadsheet Importer's manifest at build time, so the two match on SAP BTP.community org, ui5UI5 Tooling task writing the service name into the importer manifest
- ui5-middleware-approuterui5-middleware-approuterA UI5 CLI middleware that puts @sap/approuter in front of the UI5 dev server, proxying it to Cloud Foundry or XS Advanced destinations during development.community org, ui5UI5 CLI middleware proxying the dev server through @sap/approuter
- ui5-middleware-capui5-middleware-capA UI5 CLI middleware that runs a CDS server inside the UI5 dev server, mounted at a path the UI5 project configures, so one command serves the app and its CAP services.community org, ui5UI5 CLI middleware running a CDS server inside the UI5 dev server
- ui5-middleware-iasyncui5-middleware-iasyncA UI5 dev-server middleware built on browsersync.io that syncs user interactions across connected browsers over a websocket, replaying an action from one browser in the others for manual testing.community org, ui5UI5 middleware syncing interactions across browsers over websocket
- ui5-middleware-indexui5-middleware-indexA UI5 dev-server middleware that delivers a configured welcome page, index.html by default, for the root path instead of the ui5-server directory listing.community org, ui5UI5 middleware serving a chosen welcome page at the root path
- ui5-middleware-livereloadui5-middleware-livereloadA dev-server middleware that adds live reload to the UI5 dev server, reloading the page when the sources in the app's webapp folder change.community org, ui5Live reload middleware for the UI5 dev server
- ui5-middleware-oneloginui5-middleware-oneloginA UI5 dev-server middleware that logs into a system such as SAP Gateway with headless Playwright on the first request and reuses the session cookie for every later request.community org, ui5UI5 middleware logging in with Playwright and reusing the session
- ui5-middleware-serveframeworkui5-middleware-serveframeworkA UI5 middleware that serves a UI5 framework built on the local machine to the dev server, in place of a framework version resolved another way.community org, ui5UI5 middleware serving a locally built UI5 framework
- ui5-middleware-servestaticui5-middleware-servestaticA UI5 dev-server middleware that serves static resources from a filesystem path or an installed npm package path, built on serve-static, with either path settable through an environment variable.community org, ui5UI5 middleware serving static resources from a path or npm package
- ui5-middleware-simpleproxyui5-middleware-simpleproxyA UI5 dev-server middleware that proxies requests from the local dev server to a backend system, so the app can reach the backend's services during development.community org, ui5Dev-server middleware proxying requests to a backend system
- ui5-middleware-ui5ui5-middleware-ui5A UI5 middleware that lets one UI5 application be included as a dependency of another and served through that application's dev server.community org, ui5UI5 middleware including one UI5 application in another
- ui5-middleware-webjarsui5-middleware-webjarsA UI5 dev-server middleware that loads JAR files from a configured path and serves the static resources bundled inside them, following the WebJars convention of META-INF/resources/.community org, ui5UI5 middleware serving static resources from JAR files (WebJars)
- ui5-middleware-websocketui5-middleware-websocketUI5 middleware utilities that add WebSocket support to Express-based dev servers such as the UI5 server, which has no WebSocket channel of its own.community org, ui5WebSocket support for Express-based dev servers such as UI5's
- ui5-task-cachebusterui5-task-cachebusterA UI5 builder task that cachebusts a standalone UI5 application by moving its build output into a timestamped subfolder and pointing index.html's resource roots at it.community org, ui5UI5 builder task cachebusting standalone UI5 applications
- ui5-task-copyrightui5-task-copyrightA UI5 builder task that appends copyright headers to TypeScript, JavaScript and XML files on every build, so the header is not added to each source file by hand.community org, ui5UI5 builder task appending copyright headers to source files
- ui5-task-flatten-libraryui5-task-flatten-libraryA UI5 builder task that flattens a library's build output, removing the project namespace and resources folder for deployment to SAP NetWeaver, now also offered by the UI5 CLI itself.community org, ui5UI5 builder task flattening library output for SAP NetWeaver
- ui5-task-i18ncheckui5-task-i18ncheckA UI5 builder task that cross-checks every XML view against the app's i18n properties files and logs a warning where a translation is missing; views created in JavaScript are not checked.community org, ui5UI5 builder task checking XML views for missing i18n texts
- ui5-task-minify-xmlui5-task-minify-xmlA UI5 builder task that minifies XML resources such as views and fragments, which a plain UI5 build otherwise ships unminified.community org, ui5UI5 builder task minifying XML views and fragments
- ui5-task-pwa-enablerui5-task-pwa-enablerA UI5 builder task that turns a UI5 application into a progressive web app by generating a web manifest and a service worker under one of five caching strategies.community org, ui5UI5 builder task turning a UI5 app into a progressive web app
- ui5-task-zipperui5-task-zipperA build task for the UI5 tooling that packages the UI5 build result, the webapp, as a zip archive at the end of the build.community org, ui5Build task packaging the UI5 build result as a zip archive
- ui5-tooling-lessui5-tooling-lessA UI5 CLI extension, a build task and a dev-server middleware, that compiles an app's Less files into CSS at build time and live while the UI5 server runs.community org, ui5UI5 CLI extension compiling Less files into CSS
- ui5-tooling-modulesui5-tooling-modulesA set of UI5 tooling extensions that load and convert plain npm packages into UI5 AMD-like modules, so the UI5 module loader can consume them.community org, ui5UI5 tooling extensions loading npm packages as UI5 modules
- ui5-tooling-stringreplaceui5-tooling-stringreplaceA UI5 CLI extension for string replacement during the build, for placeholders or tokens in source files that have to be replaced at build time.community org, ui5UI5 CLI extension for string replacement during the build
- ui5-tooling-transpileui5-tooling-transpileA UI5 CLI extension that transpiles modern JavaScript or TypeScript during the UI5 build, with a transformJSX option that handles JSX and TSX in the same step.community org, ui5UI5 CLI extension transpiling code during the UI5 build
- @ui5/logger@ui5/loggerUI5 CLI's internal logger, described by its own readme as internal — it appears here because other UI5 tooling depends on it.sap official, ui5Internal logger of the UI5 CLI
- @ui5/middleware-code-coverage@ui5/middleware-code-coverageUI5 CLI server middleware that instruments a project's JavaScript files with Istanbul as the dev server sends them, and generates the coverage report from the records the OpenUI5 QUnit tests send back.sap official, ui5UI5 CLI middleware for Istanbul code coverage
- @ui5/tooling-webc@ui5/tooling-webcDeprecated UI5 Tooling extensions that generate UI5 library wrapper projects for UI5 Web Components and serve them during development; the README points to ui5-tooling-modules instead.sap official, ui5Deprecated UI5 Tooling extensions for UI5 Web Components wrappers
Details
Sources
Sources are graph entities: the same page may back several entries, and an unreachable source flags every row that rests on it.
Compatibility and provenance
Contributors
History in the atlas
- First seen.
For your agent
- Ref
artifact:ui5-community-ui5-middleware-hmr- JSON
- /artifacts/ui5-community-ui5-middleware-hmr.json
- MCP
- Connecting an agent