Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions internal/documentation/docs/pages/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,7 @@ server:
settings:
httpPort: 1337
httpsPort: 1443
liveReload: true
```

:::
Expand All @@ -662,6 +663,8 @@ A project can also configure alternative default ports. If the configured port i

The default and configured server ports can always be overwritten with the CLI parameter `--port`.

The `liveReload` setting controls whether the browser automatically reloads when project sources change. It defaults to `true` when running `ui5 serve` and can be overridden via the CLI parameter `--live-reload`. Requires [Specification Version](#specification-versions) 5.0 or higher.

## Extension Configuration

::: details Example
Expand Down Expand Up @@ -809,6 +812,10 @@ Version | UI5 CLI Release

### Specification Version 5.0

**Features:**

- Adds new server setting [`server.settings.liveReload`](#server-configuration) to control automatic browser reload on source changes

Specification Version 5.0 projects are supported by [UI5 CLI](https://github.com/UI5/cli) v5.0.0 and above.

### Specification Version 4.0
Expand Down
30 changes: 30 additions & 0 deletions internal/documentation/docs/pages/Server.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ A project can also add custom middleware to the server by using the [Custom Serv
| `csp` | See chapter [csp](#csp) |
| `compression` | Standard [Express compression middleware](http://expressjs.com/en/resources/middleware/compression.html) |
| `cors` | Standard [Express cors middleware](http://expressjs.com/en/resources/middleware/cors.html) |
| `liveReloadClient` | See chapter [liveReload](#livereload) |
| `discovery` | See chapter [discovery](#discovery) |
| `serveResources` | See chapter [serveResources](#serveresources) |
| `testRunner` | See chapter [testRunner](#testrunner) |
Expand Down Expand Up @@ -67,6 +68,35 @@ With `serveCSPReports` set to `true`, the CSP reports are collected and can be d

This middleware lists project files with URLs under several `/discovery` endpoints. This is exclusively used by the OpenUI5 test suite application.

### liveReload

Live reload automatically refreshes the browser whenever you change a source file in your project — no manual reload needed. This shortens the edit/test cycle during development.

#### Usage

Live reload is **enabled by default** with `ui5 serve`. Open your app in the browser, edit a source file, save — the page reloads.

To control it:

- **CLI flag**: `ui5 serve --live-reload` / `--no-live-reload`
- **Project configuration** (specVersion 5.0+): `server.settings.liveReload` in `ui5.yaml`. See [Configuration](./Configuration.md).

When the dev server is restarted, the browser automatically reconnects and reloads once the server is back. Saving multiple files at once triggers a single reload, not one per file.

#### Technical Details

The following describes how the middleware works internally. This is relevant for advanced users and custom middleware developers — not required for regular usage.

When live reload is active, the UI5 server opens a WebSocket connection that notifies the browser of source changes and triggers a page reload.

Reloads are driven by the `BuildServer`, which emits a debounced `sourcesChanged` event whenever watched source files change. A burst of changes therefore results in a single reload notification.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like the detailed documentation but I would recommend to have a more abstract / consumer friendly first section and then describing the technical details in a second section. The consumer has to know whats the benefit of this middleware and how to control it. IMHO The underlying technical aspects are only relevant for experts or custom middleware developers.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that makes sense.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally agree. There are now two sections.


The `liveReloadClient` middleware serves the client script at `/.ui5/liveReload/client.js`. The script tag is automatically injected into HTML responses by the `serveResources` middleware.

To prevent intermediate proxies from idle-closing the WebSocket, the client sends a keepalive message every 30 seconds while the connection is open. The server echoes the same message back.

When the WebSocket connection is lost (e.g. because the server was restarted), the client polls the WebSocket endpoint every second and reloads the page once the server accepts connections again. While the browser tab is hidden, polling pauses until it becomes visible again.

### serveResources
This middleware resolves requests using the [ui5-fs](https://github.com/SAP/ui5-fs)-file system abstraction.

Expand Down
15 changes: 15 additions & 0 deletions internal/documentation/docs/updates/migrate-v5.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ Or update your global install via: `npm i --global @ui5/cli@next`

- **Rename: Command Option `--cache-mode` is now `--snapshot-cache`**

- **@ui5/server: Live Reload is enabled by default for `ui5 serve`**


## Node.js and npm Version Support

Expand Down Expand Up @@ -206,6 +208,19 @@ Delete the custom `test/Test.qunit.html` file from your test directory. This fil
Depending on your project setup, you might need to update additional paths in configuration files or test runners to reflect the new structure.
The test suite is now served under the standard `/test-resources/` path with the component's full namespace (e.g. `/test-resources/sap/ui/demo/todo/testsuite.qunit.html`).

## Live Reload

UI5 CLI v5 introduces a built-in [Live Reload](../pages/Server.md#livereload) feature for the development server. When running `ui5 serve`, the browser automatically reloads whenever project sources change. Live Reload is implemented via a WebSocket connection.

Live Reload is **enabled by default**. It can be controlled via:

- The new `--live-reload` CLI flag for `ui5 serve` (defaults to `true`). Pass `--no-live-reload` to disable it.
- The new `server.settings.liveReload` configuration option in `ui5.yaml`. This setting is only available with [Specification Version 5.0](../pages/Configuration#specification-version-5-0) and higher.

::: warning Custom Live Reload Middleware
If your project uses a custom middleware that provides live reload functionality (e.g. [@sap-ux/reload-middleware](https://www.npmjs.com/package/@sap-ux/reload-middleware) or [ui5-middleware-livereload](https://www.npmjs.com/package/ui5-middleware-livereload)), the page may refresh more often than necessary when combined with the built-in feature. When upgrading, either remove the custom middleware or disable the built-in Live Reload via the `--no-live-reload` CLI flag or the `server.settings.liveReload` configuration option.
:::

## Removal of Standard Server Middleware

The following middleware has been removed from the [standard middlewares list](../pages/Server.md#standard-middleware):
Expand Down
22 changes: 22 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 19 additions & 1 deletion packages/cli/lib/cli/commands/serve.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ serve.builder = function(cli) {
default: false,
type: "boolean"
})
.option("live-reload", {
describe:
"Automatically reload the browser when project sources change. " +
"Overrides the 'liveReload' setting in the project's server configuration",
defaultDescription: "true",
type: "boolean"
})
.option("accept-remote-connections", {
describe: "Accept remote connections. By default the server only accepts connections from localhost",
default: false,
Expand Down Expand Up @@ -109,7 +116,7 @@ serve.builder = function(cli) {
"The 'Default' behavior is to invalidate the cache after 9 hours. 'Force' uses the cache only and " +
"does not create any requests. 'Off' invalidates any existing cache and updates from the repository",
type: "string",
defaultDescription: "Default", // Use "defaultdescription" to allow undefined (needed for evaluation)
defaultDescription: "Default", // Use "defaultDescription" to allow undefined (needed for evaluation)
choices: ["Default", "Force", "Off"],
})
.example("ui5 serve", "Start a web server for the current project")
Expand Down Expand Up @@ -165,11 +172,22 @@ serve.handler = async function(argv) {
}
}

let liveReload = argv.liveReload;
if (liveReload === undefined) {
const serverSettings = graph.getRoot().getServerSettings();
if (serverSettings && serverSettings.liveReload !== undefined) {
Comment thread
d3xter666 marked this conversation as resolved.
liveReload = serverSettings.liveReload;
} else {
liveReload = true;
}
}

const serverConfig = {
port,
changePortIfInUse,
h2: argv.h2,
simpleIndex: !!argv.simpleIndex,
liveReload: !!liveReload,
acceptRemoteConnections: !!argv.acceptRemoteConnections,
cert: argv.h2 ? argv.cert : undefined,
key: argv.h2 ? argv.key : undefined,
Expand Down
76 changes: 74 additions & 2 deletions packages/cli/test/lib/cli/commands/serve.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ URL: http://localhost:8080
sendSAPTargetCSP: false,
serveCSPReports: false,
simpleIndex: false,
liveReload: true,
}
]);
t.is(typeof server.serve.getCall(0).args[2], "function");
Expand Down Expand Up @@ -171,6 +172,7 @@ URL: https://localhost:8443
sendSAPTargetCSP: false,
serveCSPReports: false,
simpleIndex: false,
liveReload: true,
}
]);

Expand Down Expand Up @@ -223,6 +225,7 @@ URL: http://localhost:8080
sendSAPTargetCSP: false,
serveCSPReports: false,
simpleIndex: false,
liveReload: true,
}
]);
});
Expand Down Expand Up @@ -265,6 +268,7 @@ URL: http://localhost:8080
sendSAPTargetCSP: false,
serveCSPReports: false,
simpleIndex: false,
liveReload: true,
}
]);

Expand Down Expand Up @@ -312,6 +316,7 @@ URL: http://localhost:8080
sendSAPTargetCSP: false,
serveCSPReports: false,
simpleIndex: false,
liveReload: true,
}
]);

Expand Down Expand Up @@ -356,6 +361,7 @@ URL: http://localhost:8080
sendSAPTargetCSP: false,
serveCSPReports: false,
simpleIndex: false,
liveReload: true,
}
]);
});
Expand Down Expand Up @@ -393,7 +399,8 @@ URL: http://localhost:8080
port: 8080,
sendSAPTargetCSP: false,
serveCSPReports: false,
simpleIndex: false
simpleIndex: false,
liveReload: true
}
]);
});
Expand Down Expand Up @@ -434,7 +441,8 @@ URL: http://localhost:8080
port: 8080,
sendSAPTargetCSP: false,
serveCSPReports: false,
simpleIndex: false
simpleIndex: false,
liveReload: true
}
]);
});
Expand Down Expand Up @@ -473,6 +481,7 @@ URL: http://localhost:8080
sendSAPTargetCSP: false,
serveCSPReports: false,
simpleIndex: false,
liveReload: true,
}
]);
});
Expand Down Expand Up @@ -511,6 +520,7 @@ URL: http://localhost:8080
sendSAPTargetCSP: false,
serveCSPReports: false,
simpleIndex: false,
liveReload: true,
}
]);
});
Expand Down Expand Up @@ -549,6 +559,7 @@ URL: http://localhost:8080
sendSAPTargetCSP: false,
serveCSPReports: false,
simpleIndex: false,
liveReload: true,
}
]);
});
Expand Down Expand Up @@ -587,6 +598,7 @@ URL: http://localhost:8080
sendSAPTargetCSP: false,
serveCSPReports: false,
simpleIndex: false,
liveReload: true,
}
]);
});
Expand Down Expand Up @@ -626,6 +638,7 @@ URL: http://localhost:8080
sendSAPTargetCSP: false,
serveCSPReports: false,
simpleIndex: false,
liveReload: true,
}
]);
});
Expand Down Expand Up @@ -664,6 +677,7 @@ URL: http://localhost:8080
sendSAPTargetCSP: true,
serveCSPReports: false,
simpleIndex: false,
liveReload: true,
}
]);
});
Expand Down Expand Up @@ -702,6 +716,7 @@ URL: http://localhost:8080
sendSAPTargetCSP: false,
serveCSPReports: true,
simpleIndex: false,
liveReload: true,
}
]);
});
Expand Down Expand Up @@ -740,10 +755,64 @@ URL: http://localhost:8080
sendSAPTargetCSP: false,
serveCSPReports: false,
simpleIndex: true,
liveReload: true,
}
]);
});

test.serial("ui5 serve --no-live-reload", async (t) => {
const {argv, serve, server} = t.context;

argv.liveReload = false;

serve.handler(argv);
await t.context.handlerReady;

t.is(server.serve.callCount, 1);
t.is(server.serve.getCall(0).args[1].liveReload, false);
});

test.serial("ui5 serve --live-reload", async (t) => {
const {argv, serve, server} = t.context;

argv.liveReload = true;

serve.handler(argv);
await t.context.handlerReady;

t.is(server.serve.callCount, 1);
t.is(server.serve.getCall(0).args[1].liveReload, true);
});

test.serial("ui5 serve with ui5.yaml liveReload=false setting", async (t) => {
const {argv, serve, server, getServerSettings} = t.context;

getServerSettings.returns({
liveReload: false
});

serve.handler(argv);
await t.context.handlerReady;

t.is(server.serve.callCount, 1);
t.is(server.serve.getCall(0).args[1].liveReload, false);
});

test.serial("ui5 serve --live-reload overrides ui5.yaml liveReload setting", async (t) => {
const {argv, serve, server, getServerSettings} = t.context;

argv.liveReload = true;
getServerSettings.returns({
liveReload: false
});

serve.handler(argv);
await t.context.handlerReady;

t.is(server.serve.callCount, 1);
t.is(server.serve.getCall(0).args[1].liveReload, true);
});

test.serial("ui5 serve with ui5.yaml port setting", async (t) => {
const {argv, serve, graph, server, fakeGraph, getServerSettings} = t.context;

Expand Down Expand Up @@ -785,6 +854,7 @@ URL: http://localhost:3333
sendSAPTargetCSP: false,
serveCSPReports: false,
simpleIndex: false,
liveReload: true,
}
]);
});
Expand Down Expand Up @@ -837,6 +907,7 @@ URL: https://localhost:4444
sendSAPTargetCSP: false,
serveCSPReports: false,
simpleIndex: false,
liveReload: true,
}
]);

Expand Down Expand Up @@ -896,6 +967,7 @@ URL: https://localhost:5555
sendSAPTargetCSP: false,
serveCSPReports: false,
simpleIndex: false,
liveReload: true,
}
]);

Expand Down
Loading