From 4fedc7e34f5aefa1690da2e05bb877eff0aebb2d Mon Sep 17 00:00:00 2001 From: Max Reichmann Date: Tue, 2 Jun 2026 15:39:40 +0200 Subject: [PATCH 1/5] docs: Add Incremental Build Vitepress docs JIRA: CPOUI5FOUNDATION-1205 --- internal/documentation/docs/pages/Builder.md | 57 ++++++++++ .../documentation/docs/pages/Configuration.md | 3 + internal/documentation/docs/pages/Overview.md | 14 +++ internal/documentation/docs/pages/Server.md | 66 ++++++++++++ .../extensibility/CustomServerMiddleware.md | 27 +++++ .../docs/pages/extensibility/CustomTasks.md | 102 ++++++++++++++++++ .../documentation/docs/updates/migrate-v5.md | 101 +++++++++++++++++ 7 files changed, 370 insertions(+) diff --git a/internal/documentation/docs/pages/Builder.md b/internal/documentation/docs/pages/Builder.md index 2bf7a74fa46..262fe11bbf2 100644 --- a/internal/documentation/docs/pages/Builder.md +++ b/internal/documentation/docs/pages/Builder.md @@ -14,6 +14,63 @@ For every type there is a set of default tasks. You can disable single tasks usi +## Incremental Build and Caching + +Starting with UI5 CLI v5, UI5 project building integrates the **Incremental Build**. This architectural change brings significant benefits while introducing some behavioral differences compared to previous versions. Instead of rebuilding everything from scratch, the UI5 Builder tracks which resources have changed and which build tasks need to be re-executed: + +### How It Works + +When you start a project build with `ui5 build`: + +1. **Cache Population and Reuse**: The UI5 CLI builds your project caching build results and metadata +1. **File Watching**: When Watch Mode is enabled, the CLI monitors your source files for changes and triggers automatic rebuilds (see [Watch Mode](#watch-mode) section) +1. **Incremental Rebuilds**: When a rebuild is triggered, only relevant tasks are re-executed and cached results from unrelated ones are used +1. **Cached Results**: Build outputs are cached to gain performance during subsequent builds + +### Build Cache Control + +You can control the build cache behavior using the `--cache` option: + +- `--cache Default` (default): Use the cache if available, create it if missing +- `--cache Force`: Only use the cache; fail if the cache is unavailable or invalid +- `--cache ReadOnly`: Use existing cache but don't update it (useful for CI/CD) +- `--cache Off`: Disable caching entirely and always perform a full rebuild + +Example: +```sh +ui5 build --cache Off +``` +In this scenario, when a source file change is made, always perform a full rebuild (even if this source version already existed sometime ago). + +::: warning Important +Build caches created by `ui5 build` and `ui5 serve` are **separate and cannot be mixed**. Each command maintains its own cache optimized for its specific use case. +::: + +For more details on server caching, see the [UI5 Server documentation](./Server.md). + +### Watch Mode + +The `ui5 build` command supports a `--watch` flag that monitors source files for changes and automatically triggers incremental rebuilds: + +```sh +ui5 build --watch +``` + +When watch mode is enabled: +- Source files in your project are monitored for changes +- Incremental rebuilds are triggered automatically when changes are detected +- Only affected tasks are re-executed + +::: tip +Watch mode monitors your source files only. Changes to configuration files (`ui5.yaml`, `package.json`) or custom task implementations require restarting the build command. +::: + +::: info Info +For `ui5 serve`, this behavior is always turned on automatically. +::: + +TODO: check this section again once it's implemented + ## Tasks Tasks are specific build steps to be executed during build phase. diff --git a/internal/documentation/docs/pages/Configuration.md b/internal/documentation/docs/pages/Configuration.md index 03c6a4a2e99..661b06973e7 100644 --- a/internal/documentation/docs/pages/Configuration.md +++ b/internal/documentation/docs/pages/Configuration.md @@ -662,6 +662,9 @@ 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`. + +TODO: Add Live Reload configuration once it's implemented + ## Extension Configuration ::: details Example diff --git a/internal/documentation/docs/pages/Overview.md b/internal/documentation/docs/pages/Overview.md index 5d0b510bf81..933473bc683 100644 --- a/internal/documentation/docs/pages/Overview.md +++ b/internal/documentation/docs/pages/Overview.md @@ -3,6 +3,20 @@ When developing a UI5 project on your local system, you should use the UI5 Serve However, you might have good reasons to also use the UI5 Builder during development. In such cases, feel free to let us know! Maybe your use case could be covered by a future enhancement of the UI5 Server. +## Incremental Build and Caching + +Starting with UI5 CLI v5, both `ui5 serve` and `ui5 build` use the **Incremental Build** to improve performance: + +- Build results are cached and reused across builds and server sessions +- Only modified resources and affected build tasks are reprocessed +- The server automatically watches source files and triggers rebuilds when changes are detected +- Custom build tasks from dependencies execute automatically β€” no manual middleware configuration needed + +For more details, see: +- [UI5 Server: Incremental Build and Caching](./Server.md#incremental-build-and-caching) +- [UI5 Builder: Incremental Build and Caching](./Builder.md#incremental-build-and-caching) +- [Migration Guide: Incremental Build](../updates/migrate-v5.md#incremental-build) + ## Project Dependencies UI5 CLI differentiates between "framework dependencies" and "project dependencies". diff --git a/internal/documentation/docs/pages/Server.md b/internal/documentation/docs/pages/Server.md index 64fd885fe4a..9725aa8fc28 100644 --- a/internal/documentation/docs/pages/Server.md +++ b/internal/documentation/docs/pages/Server.md @@ -23,6 +23,66 @@ Please be aware of the following risks when using the server: ::: + +## Development Server + +Starting with UI5 CLI v5, the development server integrates with the **Incremental Build**. This architectural change brings significant benefits while introducing some behavioral differences compared to previous versions. + +### How It Works + +When you start the server with `ui5 serve`: + +1. **On-Demand Building**: The server builds your project only when a request comes in, and only if no cache exists or the cache is stale +1. **File Watching**: The server monitors your source files for changes +1. **Incremental Rebuilds**: When changes are detected and a new request is sent, an automatic rebuild is triggered containing only relevant build tasks +1. **Live Reload**: If live reload is enabled, the browser automatically refreshes once a rebuild completes (see [Live Reload](#live-reload) section) +1. **Cached Results**: Build outputs are cached to gain performance during subsequent builds + +### Benefits + +- **Faster Subsequent Builds**: The incremental build cache significantly speeds up rebuilds after the first run +- **Automatic Dependency Task Execution**: Custom build tasks defined in your project's dependencies (libraries, modules) are now executed automatically during the build. You no longer need to configure custom middleware to handle these tasks. +- **Theme Pre-Compilation**: Themes are now pre-compiled by the `buildThemes` task during the build, improving performance (see [Removed Middleware](#standard-middleware) section) + +### Server Cache Control + +You can control the build cache behavior using the `--cache` option: + +- `--cache Default` (default): Use the cache if available, create it if missing +- `--cache Force`: Only use the cache; fail if the cache is unavailable or invalid +- `--cache ReadOnly`: Use existing cache but don't update it (useful for CI/CD) +- `--cache Off`: Disable caching entirely and always perform a full rebuild + +Example: +```sh +ui5 serve --cache Off +``` +In this scenario, when a source file change is made and a request comes in, always perform a full rebuild (even if this source version already existed sometime ago). + +::: warning Important +Build caches created by `ui5 build` and `ui5 serve` are **separate and cannot be mixed**. Each command maintains its own cache optimized for its specific use case. +::: + +For more details on build caching, see the [UI5 Builder documentation](./Builder.md). + +### Watch Mode Behavior + +The server automatically watches your source files and triggers rebuilds when changes are detected: + +- **Monitored files**: All files in your project's source directories (`src/`, `webapp/`, `test/`, etc.) +- **Not monitored**: Configuration files (`ui5.yaml`, `package.json`), custom task implementations, and dependency files + +::: tip +Changes to configuration files or custom tasks require a server restart to take effect. +::: + +### Live Reload + +When Live Reload is enabled, the server automatically triggers a rebuild (utilizing caches) and notifies connected browsers to automatically refresh the page. This feature requires: + +TODO: Add explanation once live reload is implemented (CLI option + yaml config) +TODO: Mention that this supersedes ui5-livereload-middleware + ## Standard Middleware ::: info Removed Middleware @@ -87,6 +147,12 @@ Answers all non-read requests (POST, PUT, DELETE, etc.) that have not been answe ### serveIndex In case a directory has been requested, this middleware renders an HTML with a list of the directory's content. +## Standard Tasks +With UI5 CLI v5, a set of Standard Tasks is executed during a server build... +(excluding "minify", "generateLibraryPreload", "generateComponentPreload", "generateBundle") +TODO: Add list/table of standard tasks for ui5 serve (similar to Builder docs) with reference to the API docs (for more info) +TODO: Add --exclude-task explanation once and whether it's merged: "You may exclude unnecessary tasks to speed up development even more: ui5 serve --exclude-task enhanceManifest + ## SSL Certificates When starting the UI5 Server in HTTPS- or HTTP/2 mode, for example by using UI5 CLI parameter `--h2`, you will be prompted for the automatic generation of a local SSL certificate if necessary. diff --git a/internal/documentation/docs/pages/extensibility/CustomServerMiddleware.md b/internal/documentation/docs/pages/extensibility/CustomServerMiddleware.md index 1b5f22cb0aa..59100892f79 100644 --- a/internal/documentation/docs/pages/extensibility/CustomServerMiddleware.md +++ b/internal/documentation/docs/pages/extensibility/CustomServerMiddleware.md @@ -34,6 +34,33 @@ There can be optional configuration parameters which are passed directly to the An optional mountPath for which the middleware function is invoked can be provided. It will be passed to the `app.use` call (see [express API reference](https://expressjs.com/en/4x/api.html#app.use)). +### With Incremental Build + +**Change in UI5 CLI v5:** The development server now integrates with the incremental build system. When a request comes in, the server builds the project on-demand (if no cache exists or the cache is stale) before serving resources. + +- **Custom build tasks from dependencies execute automatically**: If your reusable library or module defines custom build tasks, they will be executed during the build phase. You no longer need to configure custom middleware at the root project level to handle tasks from dependencies. + +- **Middleware receives pre-built resources**: The `resources` parameter passed to your middleware implementation provides access to fully built resources, including outputs from all build tasks (both standard and custom). + +#### Accessing Build Outputs in Middleware + +The `resources` readers provided to your middleware return pre-built resources: + +```js +export default function({resources, log}) { + return async function (req, res, next) { + // This returns the built resource, including all task transformations + const resource = await resources.all.byPath(req.path); + + if (resource) { + const content = await resource.getString(); + // The content has already been processed by all build tasks + } + next(); + } +} +``` + ### Execution order Note that middleware configurations are applied in the order they are defined. When referencing another custom middleware, it has to be defined *before* that reference. diff --git a/internal/documentation/docs/pages/extensibility/CustomTasks.md b/internal/documentation/docs/pages/extensibility/CustomTasks.md index 23c27aa1c76..9cffc496ad4 100644 --- a/internal/documentation/docs/pages/extensibility/CustomTasks.md +++ b/internal/documentation/docs/pages/extensibility/CustomTasks.md @@ -103,6 +103,108 @@ task: path: lib/tasks/renderMarkdownFiles.js ``` +## Incremental Build Support + +Starting with UI5 CLI v5, the UI5 Builder supports **incremental builds** by caching task data. Custom tasks can opt into this behavior to improve performance. + +### How Incremental Builds Work for Tasks + +1. **First Execution**: The task runs normally and its outputs are cached +1. **Resource Tracking**: The build system tracks which resources the task reads and writes +1. **Cache Validation**: On subsequent builds, if the task's inputs haven't changed, the cached outputs are reused and the task is skipped +1. **Incremental Execution**: If only some inputs changed, the task can optionally process only those changed resources (see [supportsDifferentialBuilds()](#supportsDifferentialBuilds()) below) + +### Making Your Task Cache-Aware (Differential Builds) + +Custom build tasks can now optionally support **differential builds** by implementing the following new features. + +::: info Info +When a task supports differential builds, it is the task author's responsibility to ensure correctness. Specifically, if a task's output for resource A depends on the content of resource B, the task must account for this when processing only the changed resources. Tasks that cannot reliably determine such cross-resource dependencies should not enable differential build support. For example, bundling tasks β€” where the output depends on the content of many input resources β€” may not support differential builds until a more robust solution is available. +::: + +#### `supportsDifferentialBuilds()` + +TODO: Check this section again + +Indicates whether your task can process only changed resources: + +```js +/** + * Indicates whether this task can perform differential builds + * + * @returns {boolean} True if the task can process only modified resources + */ +export function supportsDifferentialBuilds() { + return true; // This task can process only changed files +} +``` + +When this returns `true`, your task's main function receives an additional parameter indicating which resources have changed. The task can then process only those resources instead of all resources. + +#### `determineBuildSignature({log, options})` + +TODO: Check this section again + +Returns `undefined` or an arbitrary string representing the build signature for the task. This can be used to incorporate task-specific configuration files into the build signature of the project, causing the cache to be invalidated if those files change. The string should not be a hash value (the build signature hash is calculated later). If `undefined` is returned, or if the method is not implemented, it is assumed that the task's cache remains valid until relevant input resources change. + +This method is called once at the beginning of every build. The return value is used to calculate a unique signature for the task based on its configuration. This signature is then incorporated into the overall build signature of the project. + +```js +/** + * Determines the build signature for this task + * + * Configuration changes that affect output should be reflected in this signature + * + * @param {object} parameters + * @param {@ui5/logger/Logger} parameters.log Logger instance + * @param {object} parameters.options Task options from ui5.yaml + * @returns {Promise} Build signature string + */ +export async function determineBuildSignature({log, options}) { + return "TODO:"; +} +``` + +**Example use case:** A TypeScript compilation task that includes the TypeScript version and `tsconfig.json` settings in its signature, so the cache is invalidated when compiler settings change. + +#### `determineExpectedOutput({workspace, dependencies, log, options})` + +TODO: Check this section again + +Declares which resources the task is expected to produce. This allows the build system to detect and remove stale outputs when the task stops producing files it previously created. + +This method is called right before the task is being executed. It is used to detect stale output resources that were produced in a previous execution of the task, but are no longer produced in the current execution. Such stale resources must be removed from the build output to avoid inconsistencies. + +```js +/** + * Determines which resources this task is expected to produce + * + * @param {object} parameters + * @param {module:@ui5/fs.DuplexCollection} parameters.workspace Reader/Writer for project resources + * @param {module:@ui5/fs.AbstractReader} parameters.dependencies Reader for dependency resources + * @param {@ui5/logger/Logger} parameters.log Logger instance + * @param {object} parameters.options Task options from ui5.yaml + * @returns {Promise>} Array of resource paths this task will produce + */ +export async function determineExpectedOutput({workspace, dependencies, log, options}) { + // Return the paths of resources this task will create + const sourceFiles = await workspace.byGlob("**/*.ts"); + return sourceFiles.map(resource => + resource.getPath().replace(/\.ts$/, ".js") + ); +} +``` + +**Example use case:** A code generator that creates JavaScript files from TypeScript sources. If a `.ts` file is deleted, the corresponding `.js` file should also be removed. + +### Best Practices for Cache-Aware Tasks + +1. **Keep tasks deterministic**: Given the same inputs, always produce the same outputs +2. **Use `determineBuildSignature`**: Include all configuration that affects output in the build signature +3. **Opt into differential builds carefully**: Only set `supportsDifferentialBuilds = true` if your task can safely process files independently +4. **Declare expected outputs**: Implement `determineExpectedOutput` if your task generates new files (not just modifies existing ones) +5. **Test cache behavior**: Verify that your task produces identical results whether running from cache or fresh execution + ## Task Implementation A custom task implementation needs to return a function with the following signature: diff --git a/internal/documentation/docs/updates/migrate-v5.md b/internal/documentation/docs/updates/migrate-v5.md index 1612bd6dfa9..f42ae0cbe7c 100644 --- a/internal/documentation/docs/updates/migrate-v5.md +++ b/internal/documentation/docs/updates/migrate-v5.md @@ -29,6 +29,107 @@ UI5 CLI 5.x introduces **Specification Version 5.0**, which enables the new Comp Projects using older **Specification Versions** are expected to be **fully compatible with UI5 CLI v5**. +## Incremental Build + +UI5 CLI v5 introduces **incremental builds with caching** for both commands `ui5 build` and `ui5 serve`. This fundamental architectural change significantly improves build performance by reusing cached results from previous builds. + +### What Changed + +**Previous Behavior (v4 and earlier):** +- Every source change resulted in an entire rebuild of all projects +- Every build executed all tasks from scratch +- No caching between builds or server sessions + +**New Behavior (v5):** +- Only relevant projects are rebuilt +- Only modified resources and affected tasks are reprocessed +- **For `ui5 build`**: Caches are used automatically when available +- **For `ui5 serve`**: When a source file change occured and a request was made, the server automatically detects this, tries to use caches and only rebuilds when none are available + +### Impact on Your Workflow + +#### Performance + +- **First build**: Probably slower, as the cache is populated with all build outputs +- **Subsequent builds**: Significantly faster β€” only modified resources and affected tasks are reprocessed +- **Quick iterations**: Changes to individual files typically rebuild very quickly +- **Cache reuse**: Caches are used between server restarts and multiple build sessions + +TODO: Include some performance stats? + +### New CLI Options + +#### `--cache` Option + +Both `ui5 build` and `ui5 serve` now support a `--cache` option to control this build cache behavior: + +| Mode | Description | +|------|-------------| +| `Default` | Use cache if available, create/update as needed (default) | +| `Force` | Only use cache; fail if unavailable or invalid | +| `ReadOnly` | Use cache but don't write to file system | +| `Off` | Disable caching and rebuild from scratch | + +Example: +```sh +ui5 serve --cache ReadOnly # Use a cache if available, rebuild if not (don't write) +ui5 serve --cache Off # Disable build caching +ui5 build --cache Force # Always try to use the cache and fail if not available +``` + +#### Watch Mode +
+ +##### ui5 serve +When using `ui5 serve`, the development server automatically: + +1. **Watches source files** for changes (files in `src/`, `webapp/`, `test/`, etc.) +1. **Triggers automatic rebuilds** when changes are detected and a request is made (when Live Reload is enabled, this is automatically handled) + +
+ +##### ui5 build +When using `ui5 build --watch`, the UI5 CLI also **watches source files** and **triggers automatic rebuilds** when changes are detected. + +::: tip +Watch mode monitors your source files only. Changes to configuration files (`ui5.yaml`, `package.json`) or custom task implementations require a server restart (or build restart for `ui5 build`). +::: + +#### Live Reload + +When using `ui5 serve --live-reload` or adding `liveReload` to the ui5.yaml config (TODO: Adjust UI5 CLI - Server Config docs), the development server **notifies the browser** to reload the page automatically. In this scenario, manual refreshes to trigger a rebuild are not required. + +TODO: Add bit more explanation about technical details (e.g. Websockets / SSE) once it's implemented. --> which browsers are supported? + +### Cache Management + +By default, the build cache is stored in `~/.ui5/buildCache/`. You can: + +- **Customize the location:** + see [Changing UI5 CLI's Data Directory](../pages/Troubleshooting.md#changing-ui5-clis-data-directory) + +- **Adjust caching behavior**: + ```sh + ui5 build --cache Off + ui5 serve --cache ReadOnly + ``` + +- **Clear the cache:** + ``` + TODO: Add cache clean command explanation + ``` + +- **Verify the cache:** + ``` + TODO: Add cache verify command explanation + ``` + +### Migration Checklist + +- **Specification Version**: Make sure to use at least **Specification Version 5.0** in your UI5 config +- **New performance expectations**: First build might be slower, but subsequent builds are much faster +- **Review custom middleware**: With this feature, tasks are executed in server sessions. For this reason, some (custom) middleware might be obsolete or cause problems (TODO: Add which specific middleware??). Projects might need to adapt their configuration + ## Rename of Command Option With UI5 CLI v5, the option `--cache-mode` (for commands `ui5 build` and `ui5 serve`) has been renamed to `--snapshot-cache`. From 492ca1935fa49142591b31986e3b34eb35f1f69c Mon Sep 17 00:00:00 2001 From: Max Reichmann Date: Thu, 11 Jun 2026 19:12:19 +0200 Subject: [PATCH 2/5] docs: Refactor pages - Drop phrase "Incremental Build" and use "Build Cache" instead - Remove "Starting with v5" everywhere except migration guide - Restructured migration guide section - Refactor Custom task, Builder and Server pages - Remove TODOs & Drop changes for unrelated pages --- internal/documentation/docs/pages/Builder.md | 84 ++++------- .../documentation/docs/pages/Configuration.md | 3 - internal/documentation/docs/pages/Overview.md | 14 -- internal/documentation/docs/pages/Server.md | 105 ++++++-------- .../extensibility/CustomServerMiddleware.md | 27 ---- .../docs/pages/extensibility/CustomTasks.md | 132 ++++-------------- .../documentation/docs/updates/migrate-v5.md | 92 +++--------- 7 files changed, 112 insertions(+), 345 deletions(-) diff --git a/internal/documentation/docs/pages/Builder.md b/internal/documentation/docs/pages/Builder.md index 262fe11bbf2..e314866932d 100644 --- a/internal/documentation/docs/pages/Builder.md +++ b/internal/documentation/docs/pages/Builder.md @@ -14,63 +14,6 @@ For every type there is a set of default tasks. You can disable single tasks usi -## Incremental Build and Caching - -Starting with UI5 CLI v5, UI5 project building integrates the **Incremental Build**. This architectural change brings significant benefits while introducing some behavioral differences compared to previous versions. Instead of rebuilding everything from scratch, the UI5 Builder tracks which resources have changed and which build tasks need to be re-executed: - -### How It Works - -When you start a project build with `ui5 build`: - -1. **Cache Population and Reuse**: The UI5 CLI builds your project caching build results and metadata -1. **File Watching**: When Watch Mode is enabled, the CLI monitors your source files for changes and triggers automatic rebuilds (see [Watch Mode](#watch-mode) section) -1. **Incremental Rebuilds**: When a rebuild is triggered, only relevant tasks are re-executed and cached results from unrelated ones are used -1. **Cached Results**: Build outputs are cached to gain performance during subsequent builds - -### Build Cache Control - -You can control the build cache behavior using the `--cache` option: - -- `--cache Default` (default): Use the cache if available, create it if missing -- `--cache Force`: Only use the cache; fail if the cache is unavailable or invalid -- `--cache ReadOnly`: Use existing cache but don't update it (useful for CI/CD) -- `--cache Off`: Disable caching entirely and always perform a full rebuild - -Example: -```sh -ui5 build --cache Off -``` -In this scenario, when a source file change is made, always perform a full rebuild (even if this source version already existed sometime ago). - -::: warning Important -Build caches created by `ui5 build` and `ui5 serve` are **separate and cannot be mixed**. Each command maintains its own cache optimized for its specific use case. -::: - -For more details on server caching, see the [UI5 Server documentation](./Server.md). - -### Watch Mode - -The `ui5 build` command supports a `--watch` flag that monitors source files for changes and automatically triggers incremental rebuilds: - -```sh -ui5 build --watch -``` - -When watch mode is enabled: -- Source files in your project are monitored for changes -- Incremental rebuilds are triggered automatically when changes are detected -- Only affected tasks are re-executed - -::: tip -Watch mode monitors your source files only. Changes to configuration files (`ui5.yaml`, `package.json`) or custom task implementations require restarting the build command. -::: - -::: info Info -For `ui5 serve`, this behavior is always turned on automatically. -::: - -TODO: check this section again once it's implemented - ## Tasks Tasks are specific build steps to be executed during build phase. @@ -256,3 +199,30 @@ sap.ui.define([], () => { text-decoration: inherit; } + +## Build Cache Control + +The UI5 Builder integrates **build caches**. Instead of rebuilding everything from scratch, the UI5 Builder tracks which resources have changed and which build tasks need to be re-executed: + +You can control the build cache behavior using the `--cache` option: + +- `--cache Default` (default): Use the cache if available, create it if missing +- `--cache Force`: Only use the cache; fail if the cache is unavailable or invalid +- `--cache ReadOnly`: Use existing cache but don't update it (useful for CI/CD) +- `--cache Off`: Disable caching entirely and always perform a full rebuild + +Example: +```sh +ui5 build --cache Off +``` +In this scenario, when a source file change is made, always perform a full rebuild (even if this source version already existed sometime ago). + +::: info +By default, the build cache is stored inside UI5 CLI's Data Dir (`~/.ui5/buildCache/`). You can customize the location (see [Changing UI5 CLI's Data Directory](./Troubleshooting#changing-ui5-cli-s-data-directory)). +::: + +::: info +Build caches created by `ui5 build` and `ui5 serve` are **separate and cannot be mixed**. Each command maintains its own cache optimized for its specific use case. For more details on server caching, see the [UI5 Server documentation](./Server.md). +::: + + diff --git a/internal/documentation/docs/pages/Configuration.md b/internal/documentation/docs/pages/Configuration.md index 661b06973e7..03c6a4a2e99 100644 --- a/internal/documentation/docs/pages/Configuration.md +++ b/internal/documentation/docs/pages/Configuration.md @@ -662,9 +662,6 @@ 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`. - -TODO: Add Live Reload configuration once it's implemented - ## Extension Configuration ::: details Example diff --git a/internal/documentation/docs/pages/Overview.md b/internal/documentation/docs/pages/Overview.md index 933473bc683..5d0b510bf81 100644 --- a/internal/documentation/docs/pages/Overview.md +++ b/internal/documentation/docs/pages/Overview.md @@ -3,20 +3,6 @@ When developing a UI5 project on your local system, you should use the UI5 Serve However, you might have good reasons to also use the UI5 Builder during development. In such cases, feel free to let us know! Maybe your use case could be covered by a future enhancement of the UI5 Server. -## Incremental Build and Caching - -Starting with UI5 CLI v5, both `ui5 serve` and `ui5 build` use the **Incremental Build** to improve performance: - -- Build results are cached and reused across builds and server sessions -- Only modified resources and affected build tasks are reprocessed -- The server automatically watches source files and triggers rebuilds when changes are detected -- Custom build tasks from dependencies execute automatically β€” no manual middleware configuration needed - -For more details, see: -- [UI5 Server: Incremental Build and Caching](./Server.md#incremental-build-and-caching) -- [UI5 Builder: Incremental Build and Caching](./Builder.md#incremental-build-and-caching) -- [Migration Guide: Incremental Build](../updates/migrate-v5.md#incremental-build) - ## Project Dependencies UI5 CLI differentiates between "framework dependencies" and "project dependencies". diff --git a/internal/documentation/docs/pages/Server.md b/internal/documentation/docs/pages/Server.md index 9725aa8fc28..31b36fb6bb6 100644 --- a/internal/documentation/docs/pages/Server.md +++ b/internal/documentation/docs/pages/Server.md @@ -23,66 +23,6 @@ Please be aware of the following risks when using the server: ::: - -## Development Server - -Starting with UI5 CLI v5, the development server integrates with the **Incremental Build**. This architectural change brings significant benefits while introducing some behavioral differences compared to previous versions. - -### How It Works - -When you start the server with `ui5 serve`: - -1. **On-Demand Building**: The server builds your project only when a request comes in, and only if no cache exists or the cache is stale -1. **File Watching**: The server monitors your source files for changes -1. **Incremental Rebuilds**: When changes are detected and a new request is sent, an automatic rebuild is triggered containing only relevant build tasks -1. **Live Reload**: If live reload is enabled, the browser automatically refreshes once a rebuild completes (see [Live Reload](#live-reload) section) -1. **Cached Results**: Build outputs are cached to gain performance during subsequent builds - -### Benefits - -- **Faster Subsequent Builds**: The incremental build cache significantly speeds up rebuilds after the first run -- **Automatic Dependency Task Execution**: Custom build tasks defined in your project's dependencies (libraries, modules) are now executed automatically during the build. You no longer need to configure custom middleware to handle these tasks. -- **Theme Pre-Compilation**: Themes are now pre-compiled by the `buildThemes` task during the build, improving performance (see [Removed Middleware](#standard-middleware) section) - -### Server Cache Control - -You can control the build cache behavior using the `--cache` option: - -- `--cache Default` (default): Use the cache if available, create it if missing -- `--cache Force`: Only use the cache; fail if the cache is unavailable or invalid -- `--cache ReadOnly`: Use existing cache but don't update it (useful for CI/CD) -- `--cache Off`: Disable caching entirely and always perform a full rebuild - -Example: -```sh -ui5 serve --cache Off -``` -In this scenario, when a source file change is made and a request comes in, always perform a full rebuild (even if this source version already existed sometime ago). - -::: warning Important -Build caches created by `ui5 build` and `ui5 serve` are **separate and cannot be mixed**. Each command maintains its own cache optimized for its specific use case. -::: - -For more details on build caching, see the [UI5 Builder documentation](./Builder.md). - -### Watch Mode Behavior - -The server automatically watches your source files and triggers rebuilds when changes are detected: - -- **Monitored files**: All files in your project's source directories (`src/`, `webapp/`, `test/`, etc.) -- **Not monitored**: Configuration files (`ui5.yaml`, `package.json`), custom task implementations, and dependency files - -::: tip -Changes to configuration files or custom tasks require a server restart to take effect. -::: - -### Live Reload - -When Live Reload is enabled, the server automatically triggers a rebuild (utilizing caches) and notifies connected browsers to automatically refresh the page. This feature requires: - -TODO: Add explanation once live reload is implemented (CLI option + yaml config) -TODO: Mention that this supersedes ui5-livereload-middleware - ## Standard Middleware ::: info Removed Middleware @@ -148,10 +88,47 @@ Answers all non-read requests (POST, PUT, DELETE, etc.) that have not been answe In case a directory has been requested, this middleware renders an HTML with a list of the directory's content. ## Standard Tasks -With UI5 CLI v5, a set of Standard Tasks is executed during a server build... -(excluding "minify", "generateLibraryPreload", "generateComponentPreload", "generateBundle") -TODO: Add list/table of standard tasks for ui5 serve (similar to Builder docs) with reference to the API docs (for more info) -TODO: Add --exclude-task explanation once and whether it's merged: "You may exclude unnecessary tasks to speed up development even more: ui5 serve --exclude-task enhanceManifest +As with the UI5 Builder, a set of standard tasks is being executed during a server build. However, following tasks are being **excluded by default**: +- `minify` +- `generateLibraryPreload` +- `generateComponentPreload` +- `generateBundle` + +::: info +See [Builder Standard Tasks](./Builder.md#standard-tasks) for more explanation about each task. +::: + +## Build Cache Control + +The UI5 Server performs a build of the projects by utilizing **build caches**. + +You can control the build cache behavior using the `--cache` option: + +- `--cache Default` (default): Use the cache if available, create it if missing +- `--cache Force`: Only use the cache; fail if the cache is unavailable or invalid +- `--cache ReadOnly`: Use existing cache but don't update it (useful for CI/CD) +- `--cache Off`: Disable caching entirely and always perform a full rebuild + +Example: +```sh +ui5 serve --cache Off +``` +In this scenario, when a source file change is made and a request comes in, the server always performs a full rebuild (even if this source version already existed sometime ago). + +::: info +Build caches created by `ui5 build` and `ui5 serve` are **separate and cannot be mixed**. Each command maintains its own cache optimized for its specific use case. For more details on builder caching, see the [UI5 Builder documentation](./Builder.md). +::: + +### Watch Mode Behavior + +Once started with `ui5 serve`, the server automatically keeps watch over changes to the source files throughout the session. When a request arrives, it checks for cached results first and only triggers a rebuild of the respective resources and tasks if no cache is available. + +- **Monitored files**: All files in your project's source directories (`src/`, `webapp/`, `test/`, etc.) +- **Not monitored**: Configuration files (`ui5.yaml`, `package.json`), custom task implementations, and dependency files + +::: info +Changes to configuration files or custom tasks require a server restart to take effect. +::: ## SSL Certificates When starting the UI5 Server in HTTPS- or HTTP/2 mode, for example by using UI5 CLI parameter `--h2`, you will be prompted for the automatic generation of a local SSL certificate if necessary. diff --git a/internal/documentation/docs/pages/extensibility/CustomServerMiddleware.md b/internal/documentation/docs/pages/extensibility/CustomServerMiddleware.md index 59100892f79..1b5f22cb0aa 100644 --- a/internal/documentation/docs/pages/extensibility/CustomServerMiddleware.md +++ b/internal/documentation/docs/pages/extensibility/CustomServerMiddleware.md @@ -34,33 +34,6 @@ There can be optional configuration parameters which are passed directly to the An optional mountPath for which the middleware function is invoked can be provided. It will be passed to the `app.use` call (see [express API reference](https://expressjs.com/en/4x/api.html#app.use)). -### With Incremental Build - -**Change in UI5 CLI v5:** The development server now integrates with the incremental build system. When a request comes in, the server builds the project on-demand (if no cache exists or the cache is stale) before serving resources. - -- **Custom build tasks from dependencies execute automatically**: If your reusable library or module defines custom build tasks, they will be executed during the build phase. You no longer need to configure custom middleware at the root project level to handle tasks from dependencies. - -- **Middleware receives pre-built resources**: The `resources` parameter passed to your middleware implementation provides access to fully built resources, including outputs from all build tasks (both standard and custom). - -#### Accessing Build Outputs in Middleware - -The `resources` readers provided to your middleware return pre-built resources: - -```js -export default function({resources, log}) { - return async function (req, res, next) { - // This returns the built resource, including all task transformations - const resource = await resources.all.byPath(req.path); - - if (resource) { - const content = await resource.getString(); - // The content has already been processed by all build tasks - } - next(); - } -} -``` - ### Execution order Note that middleware configurations are applied in the order they are defined. When referencing another custom middleware, it has to be defined *before* that reference. diff --git a/internal/documentation/docs/pages/extensibility/CustomTasks.md b/internal/documentation/docs/pages/extensibility/CustomTasks.md index 9cffc496ad4..33a67d0f910 100644 --- a/internal/documentation/docs/pages/extensibility/CustomTasks.md +++ b/internal/documentation/docs/pages/extensibility/CustomTasks.md @@ -103,108 +103,6 @@ task: path: lib/tasks/renderMarkdownFiles.js ``` -## Incremental Build Support - -Starting with UI5 CLI v5, the UI5 Builder supports **incremental builds** by caching task data. Custom tasks can opt into this behavior to improve performance. - -### How Incremental Builds Work for Tasks - -1. **First Execution**: The task runs normally and its outputs are cached -1. **Resource Tracking**: The build system tracks which resources the task reads and writes -1. **Cache Validation**: On subsequent builds, if the task's inputs haven't changed, the cached outputs are reused and the task is skipped -1. **Incremental Execution**: If only some inputs changed, the task can optionally process only those changed resources (see [supportsDifferentialBuilds()](#supportsDifferentialBuilds()) below) - -### Making Your Task Cache-Aware (Differential Builds) - -Custom build tasks can now optionally support **differential builds** by implementing the following new features. - -::: info Info -When a task supports differential builds, it is the task author's responsibility to ensure correctness. Specifically, if a task's output for resource A depends on the content of resource B, the task must account for this when processing only the changed resources. Tasks that cannot reliably determine such cross-resource dependencies should not enable differential build support. For example, bundling tasks β€” where the output depends on the content of many input resources β€” may not support differential builds until a more robust solution is available. -::: - -#### `supportsDifferentialBuilds()` - -TODO: Check this section again - -Indicates whether your task can process only changed resources: - -```js -/** - * Indicates whether this task can perform differential builds - * - * @returns {boolean} True if the task can process only modified resources - */ -export function supportsDifferentialBuilds() { - return true; // This task can process only changed files -} -``` - -When this returns `true`, your task's main function receives an additional parameter indicating which resources have changed. The task can then process only those resources instead of all resources. - -#### `determineBuildSignature({log, options})` - -TODO: Check this section again - -Returns `undefined` or an arbitrary string representing the build signature for the task. This can be used to incorporate task-specific configuration files into the build signature of the project, causing the cache to be invalidated if those files change. The string should not be a hash value (the build signature hash is calculated later). If `undefined` is returned, or if the method is not implemented, it is assumed that the task's cache remains valid until relevant input resources change. - -This method is called once at the beginning of every build. The return value is used to calculate a unique signature for the task based on its configuration. This signature is then incorporated into the overall build signature of the project. - -```js -/** - * Determines the build signature for this task - * - * Configuration changes that affect output should be reflected in this signature - * - * @param {object} parameters - * @param {@ui5/logger/Logger} parameters.log Logger instance - * @param {object} parameters.options Task options from ui5.yaml - * @returns {Promise} Build signature string - */ -export async function determineBuildSignature({log, options}) { - return "TODO:"; -} -``` - -**Example use case:** A TypeScript compilation task that includes the TypeScript version and `tsconfig.json` settings in its signature, so the cache is invalidated when compiler settings change. - -#### `determineExpectedOutput({workspace, dependencies, log, options})` - -TODO: Check this section again - -Declares which resources the task is expected to produce. This allows the build system to detect and remove stale outputs when the task stops producing files it previously created. - -This method is called right before the task is being executed. It is used to detect stale output resources that were produced in a previous execution of the task, but are no longer produced in the current execution. Such stale resources must be removed from the build output to avoid inconsistencies. - -```js -/** - * Determines which resources this task is expected to produce - * - * @param {object} parameters - * @param {module:@ui5/fs.DuplexCollection} parameters.workspace Reader/Writer for project resources - * @param {module:@ui5/fs.AbstractReader} parameters.dependencies Reader for dependency resources - * @param {@ui5/logger/Logger} parameters.log Logger instance - * @param {object} parameters.options Task options from ui5.yaml - * @returns {Promise>} Array of resource paths this task will produce - */ -export async function determineExpectedOutput({workspace, dependencies, log, options}) { - // Return the paths of resources this task will create - const sourceFiles = await workspace.byGlob("**/*.ts"); - return sourceFiles.map(resource => - resource.getPath().replace(/\.ts$/, ".js") - ); -} -``` - -**Example use case:** A code generator that creates JavaScript files from TypeScript sources. If a `.ts` file is deleted, the corresponding `.js` file should also be removed. - -### Best Practices for Cache-Aware Tasks - -1. **Keep tasks deterministic**: Given the same inputs, always produce the same outputs -2. **Use `determineBuildSignature`**: Include all configuration that affects output in the build signature -3. **Opt into differential builds carefully**: Only set `supportsDifferentialBuilds = true` if your task can safely process files independently -4. **Declare expected outputs**: Implement `determineExpectedOutput` if your task generates new files (not just modifies existing ones) -5. **Test cache behavior**: Verify that your task produces identical results whether running from cache or fresh execution - ## Task Implementation A custom task implementation needs to return a function with the following signature: @@ -388,11 +286,37 @@ module.exports.determineRequiredDependencies = async function({availableDependen ``` ::: +### "Cache-aware" Tasks + +Due to UI5 Builder and UI5 Server supporting **build caches** of task data, custom tasks can opt into this behavior to improve performance. This is done by implementing the following features: + +#### `supportsDifferentialBuilds()` + +This method indicates whether your task can perform differential builds: + +```js +/** + * Indicates whether this task can perform differential builds + * + * @returns {boolean} True if the task can process only modified resources + */ +export function supportsDifferentialBuilds() { + return true; +} +``` + +When this returns `true`, your task's main function receives an additional parameter indicating which resources have changed. The task can then process only those resources instead of all resources. + +::: info Best Practices for Cache-aware Tasks +1. **Keep tasks deterministic**: Given the same inputs, always produce the same outputs +2. **Opt into differential builds carefully**: Only set `supportsDifferentialBuilds = true` if your task can safely process files independently +::: + ### Examples The following code snippets show examples for custom task implementations. -### Example: lib/tasks/renderMarkdownFiles.js +#### Example: lib/tasks/renderMarkdownFiles.js This example is making use of the `resourceFactory` [TaskUtil](https://ui5.github.io/cli/v5/api/@ui5_project_build_helpers_TaskUtil.html) API to create new resources based on the output of a third-party module for rendering Markdown files. The created resources are added to the build @@ -466,7 +390,7 @@ Tasks should ideally use the reader/writer APIs provided by UI5 CLI for working ::: -### Example: lib/tasks/compileLicenseSummary.js +#### Example: lib/tasks/compileLicenseSummary.js This example is making use of multiple [TaskUtil](https://ui5.github.io/cli/v5/api/@ui5_project_build_helpers_TaskUtil.html) APIs to retrieve additional information about the project currently being built (`taskUtil.getProject()`) and its direct dependencies diff --git a/internal/documentation/docs/updates/migrate-v5.md b/internal/documentation/docs/updates/migrate-v5.md index f42ae0cbe7c..bcb8d74ceb3 100644 --- a/internal/documentation/docs/updates/migrate-v5.md +++ b/internal/documentation/docs/updates/migrate-v5.md @@ -29,106 +29,46 @@ UI5 CLI 5.x introduces **Specification Version 5.0**, which enables the new Comp Projects using older **Specification Versions** are expected to be **fully compatible with UI5 CLI v5**. -## Incremental Build +## Build Cache -UI5 CLI v5 introduces **incremental builds with caching** for both commands `ui5 build` and `ui5 serve`. This fundamental architectural change significantly improves build performance by reusing cached results from previous builds. +UI5 CLI v5 introduces **builds with caching** for both commands `ui5 build` and `ui5 serve`. This fundamental architectural change significantly improves build performance by reusing cached results from previous builds. ### What Changed **Previous Behavior (v4 and earlier):** - Every source change resulted in an entire rebuild of all projects -- Every build executed all tasks from scratch +- Every build re-executed all tasks - No caching between builds or server sessions **New Behavior (v5):** - Only relevant projects are rebuilt -- Only modified resources and affected tasks are reprocessed -- **For `ui5 build`**: Caches are used automatically when available -- **For `ui5 serve`**: When a source file change occured and a request was made, the server automatically detects this, tries to use caches and only rebuilds when none are available +- Only modified resources and affected tasks are re-processed ### Impact on Your Workflow -#### Performance - -- **First build**: Probably slower, as the cache is populated with all build outputs +- **First build**: Probably slightly slower, as the cache is populated with all build outputs - **Subsequent builds**: Significantly faster β€” only modified resources and affected tasks are reprocessed - **Quick iterations**: Changes to individual files typically rebuild very quickly -- **Cache reuse**: Caches are used between server restarts and multiple build sessions - -TODO: Include some performance stats? - -### New CLI Options - -#### `--cache` Option - -Both `ui5 build` and `ui5 serve` now support a `--cache` option to control this build cache behavior: - -| Mode | Description | -|------|-------------| -| `Default` | Use cache if available, create/update as needed (default) | -| `Force` | Only use cache; fail if unavailable or invalid | -| `ReadOnly` | Use cache but don't write to file system | -| `Off` | Disable caching and rebuild from scratch | - -Example: -```sh -ui5 serve --cache ReadOnly # Use a cache if available, rebuild if not (don't write) -ui5 serve --cache Off # Disable build caching -ui5 build --cache Force # Always try to use the cache and fail if not available -``` - -#### Watch Mode -
+- **Cross-session**: Caches are used between server restarts and build runs -##### ui5 serve -When using `ui5 serve`, the development server automatically: +### For `ui5 build` -1. **Watches source files** for changes (files in `src/`, `webapp/`, `test/`, etc.) -1. **Triggers automatic rebuilds** when changes are detected and a request is made (when Live Reload is enabled, this is automatically handled) +When `ui5 build` is executed, build caches are automatically serialized and reused when available. -
- -##### ui5 build -When using `ui5 build --watch`, the UI5 CLI also **watches source files** and **triggers automatic rebuilds** when changes are detected. - -::: tip -Watch mode monitors your source files only. Changes to configuration files (`ui5.yaml`, `package.json`) or custom task implementations require a server restart (or build restart for `ui5 build`). +::: tip Tip for Single Builds (e.g. CI/CD) +If you plan to execute a build only once (e.g. during a CI run), consider using `--cache "Off"` (see [Build Cache Control](../pages/Builder.md#build-cache-control)) to skip cache serialization. ::: -#### Live Reload - -When using `ui5 serve --live-reload` or adding `liveReload` to the ui5.yaml config (TODO: Adjust UI5 CLI - Server Config docs), the development server **notifies the browser** to reload the page automatically. In this scenario, manual refreshes to trigger a rebuild are not required. - -TODO: Add bit more explanation about technical details (e.g. Websockets / SSE) once it's implemented. --> which browsers are supported? - -### Cache Management +### For `ui5 serve` -By default, the build cache is stored in `~/.ui5/buildCache/`. You can: +During a server session (started by `ui5 serve`), source changes are automatically being monitered. Then, if a request was made, the server detects this, tries to use caches and only rebuilds when none are available. For more information see [Watch Mode Behavior](../pages/Server.md#watch-mode-behavior). -- **Customize the location:** - see [Changing UI5 CLI's Data Directory](../pages/Troubleshooting.md#changing-ui5-clis-data-directory) +::: info Review custom middleware -- **Adjust caching behavior**: - ```sh - ui5 build --cache Off - ui5 serve --cache ReadOnly - ``` +With this feature, **build tasks are executed in server sessions**. For this reason, some custom middleware might be obsolete or cause problems. Projects utilizing such might need to adapt their configuration. -- **Clear the cache:** - ``` - TODO: Add cache clean command explanation - ``` - -- **Verify the cache:** - ``` - TODO: Add cache verify command explanation - ``` - -### Migration Checklist - -- **Specification Version**: Make sure to use at least **Specification Version 5.0** in your UI5 config -- **New performance expectations**: First build might be slower, but subsequent builds are much faster -- **Review custom middleware**: With this feature, tasks are executed in server sessions. For this reason, some (custom) middleware might be obsolete or cause problems (TODO: Add which specific middleware??). Projects might need to adapt their configuration +E.g. Middleware for browser live reloads is obsolete and can be removed. Also, middleware for Typescript transpilation is not required anymore (as long as the respective task is still set up). +::: ## Rename of Command Option From 07e895c397eb1d0d4bc7d1d3050e14e363923640 Mon Sep 17 00:00:00 2001 From: Max Reichmann Date: Tue, 16 Jun 2026 12:50:15 +0200 Subject: [PATCH 3/5] docs: Refactor pages (Address review) * Adjust Custom Task explanation + code examples * Remove phrase "Incremental Build" in untouched docs * Refactor "Build caches separate" info section (Builder + Server) * Highlight servers executing builds + making middleware obsolete in migration guide (+Hint for proxies) --- internal/documentation/docs/pages/Builder.md | 2 +- internal/documentation/docs/pages/Server.md | 4 +- .../docs/pages/extensibility/CustomTasks.md | 115 +++++++++++++----- .../documentation/docs/updates/migrate-v5.md | 17 +-- 4 files changed, 98 insertions(+), 40 deletions(-) diff --git a/internal/documentation/docs/pages/Builder.md b/internal/documentation/docs/pages/Builder.md index e314866932d..f3bf7d36cb4 100644 --- a/internal/documentation/docs/pages/Builder.md +++ b/internal/documentation/docs/pages/Builder.md @@ -222,7 +222,7 @@ By default, the build cache is stored inside UI5 CLI's Data Dir (`~/.ui5/buildCa ::: ::: info -Build caches created by `ui5 build` and `ui5 serve` are **separate and cannot be mixed**. Each command maintains its own cache optimized for its specific use case. For more details on server caching, see the [UI5 Server documentation](./Server.md). +By default, build caches created by `ui5 build` and `ui5 serve` are **separate and cannot be mixed**. Each command executes a distinct set of tasks, resulting in separate caches tailored to its specific use case. For more details on server caching, see the [UI5 Server documentation](./Server.md). ::: diff --git a/internal/documentation/docs/pages/Server.md b/internal/documentation/docs/pages/Server.md index 31b36fb6bb6..61ed43e118e 100644 --- a/internal/documentation/docs/pages/Server.md +++ b/internal/documentation/docs/pages/Server.md @@ -26,7 +26,7 @@ Please be aware of the following risks when using the server: ## Standard Middleware ::: info Removed Middleware -The `serveThemes` middleware has been removed in UI5 CLI v5. Theme compilation is now handled by the `buildThemes` build task during the incremental build, which pre-compiles all theme CSS files. The resulting CSS files (including `library.css`, `library-RTL.css`, `library-parameters.json`, and CSS Variables resources) are served via the `serveResources` middleware, providing the same functionality with better performance through build-time compilation and caching. +The `serveThemes` middleware has been removed in UI5 CLI v5. Theme compilation is now handled by the `buildThemes` build task, which pre-compiles all theme CSS files. The resulting CSS files (including `library.css`, `library-RTL.css`, `library-parameters.json`, and CSS Variables resources) are served via the `serveResources` middleware, providing the same functionality with better performance through build-time compilation and caching. Custom middleware previously referencing `serveThemes` via `beforeMiddleware` or `afterMiddleware` will continue to work with automatic remapping and a deprecation warning. See the [v5 migration guide](../updates/migrate-v5.md) for details. ::: @@ -116,7 +116,7 @@ ui5 serve --cache Off In this scenario, when a source file change is made and a request comes in, the server always performs a full rebuild (even if this source version already existed sometime ago). ::: info -Build caches created by `ui5 build` and `ui5 serve` are **separate and cannot be mixed**. Each command maintains its own cache optimized for its specific use case. For more details on builder caching, see the [UI5 Builder documentation](./Builder.md). +By default, build caches created by `ui5 build` and `ui5 serve` are **separate and cannot be mixed**. Each command executes a distinct set of tasks, resulting in separate caches tailored to its specific use case. For more details on builder caching, see the [UI5 Builder documentation](./Builder.md). ::: ### Watch Mode Behavior diff --git a/internal/documentation/docs/pages/extensibility/CustomTasks.md b/internal/documentation/docs/pages/extensibility/CustomTasks.md index 33a67d0f910..ac78deca51f 100644 --- a/internal/documentation/docs/pages/extensibility/CustomTasks.md +++ b/internal/documentation/docs/pages/extensibility/CustomTasks.md @@ -128,6 +128,14 @@ A custom task implementation needs to return a function with the following signa * Namespace of the project currently being built * @param {string} parameters.options.configuration * Custom task configuration, as defined in the project's ui5.yaml + * @param {string[] | undefined} parameters.changedProjectResourcePaths + * List of changed resource paths since last execution. + * Only use if the task supports differential builds (supportsDifferentialBuilds=true). + * Returns undefined if unsupported or no cache is available. + * @param {string[] | undefined} parameters.changedDependencyResourcePaths + * List of changed dependency resource paths since last execution. + * Only use if the task supports differential builds (supportsDifferentialBuilds=true). + * Returns undefined if unsupported or no cache is available. * @param {string} parameters.options.taskName * Name of the custom task. * This parameter is only provided to custom task extensions @@ -166,6 +174,14 @@ export default async function({dependencies, log, options, taskUtil, workspace}) * Namespace of the project currently being built * @param {string} parameters.options.configuration * Custom task configuration, as defined in the project's ui5.yaml + * @param {string[] | undefined} parameters.changedProjectResourcePaths + * List of changed resource paths since last execution. + * Only use if the task supports differential builds (supportsDifferentialBuilds=true). + * Returns undefined if unsupported or no cache is available. + * @param {string[] | undefined} parameters.changedDependencyResourcePaths + * List of changed dependency resource paths since last execution. + * Only use if the task supports differential builds (supportsDifferentialBuilds=true). + * Returns undefined if unsupported or no cache is available. * @param {string} parameters.options.taskName * Name of the custom task. * This parameter is only provided to custom task extensions @@ -288,24 +304,42 @@ module.exports.determineRequiredDependencies = async function({availableDependen ### "Cache-aware" Tasks -Due to UI5 Builder and UI5 Server supporting **build caches** of task data, custom tasks can opt into this behavior to improve performance. This is done by implementing the following features: +Due to UI5 Builder and UI5 Server supporting **build caches** of task data, custom tasks can opt into this behavior to improve performance. This is done by exporting optional callback functions in your task implementation: #### `supportsDifferentialBuilds()` -This method indicates whether your task can perform differential builds: - -```js +::: code-group +```js [ESM] /** - * Indicates whether this task can perform differential builds - * - * @returns {boolean} True if the task can process only modified resources + * Indicates whether the task supports differential builds + * + * Tasks that support differential builds can use incremental cache invalidation, + * processing only changed resources rather than rebuilding from scratch. + * + * @public + * @returns {boolean} True if differential builds are supported */ export function supportsDifferentialBuilds() { return true; } ``` -When this returns `true`, your task's main function receives an additional parameter indicating which resources have changed. The task can then process only those resources instead of all resources. +```js [CommonJS] +/** + * Indicates whether the task supports differential builds + * + * Tasks that support differential builds can use incremental cache invalidation, + * processing only changed resources rather than rebuilding from scratch. + * + * @public + * @returns {boolean} True if differential builds are supported + */ +module.exports.supportsDifferentialBuilds = function() { + return true; +} +``` + +When this returns `true`, your task's main function receives an additional parameter `changedProjectResourcePaths` providing an array of changed resource paths (strings) since its last execution. The task can then process only those resources instead of all resources. If this callback is not provided (or it returns a falsy value), your task will not be able to use incremental cache invalidation and processes all resources from scratch. ::: info Best Practices for Cache-aware Tasks 1. **Keep tasks deterministic**: Given the same inputs, always produce the same outputs @@ -321,6 +355,7 @@ The following code snippets show examples for custom task implementations. This example is making use of the `resourceFactory` [TaskUtil](https://ui5.github.io/cli/v5/api/@ui5_project_build_helpers_TaskUtil.html) API to create new resources based on the output of a third-party module for rendering Markdown files. The created resources are added to the build result by writing them into the provided `workspace`. +In addition, differential builds are supported by this task which re-processes only changed resources. ::: code-group @@ -331,26 +366,37 @@ import renderMarkdown from "./renderMarkdown.js"; /* * Render all .md (Markdown) files in the project to HTML */ -export default async function({dependencies, log, options, taskUtil, workspace}) { +export default async function({dependencies, log, options, taskUtil, workspace, changedProjectResourcePaths}) { const {createResource} = taskUtil.resourceFactory; - const textResources = await workspace.byGlob("**/*.md"); - await Promise.all(textResources.map(async (resource) => { - const markdownResourcePath = resource.getPath(); - - log.info(`Rendering markdown file ${markdownResourcePath}...`); - const htmlString = await renderMarkdown(await resource.getString(), options.configuration); - - // Note: @ui5/fs virtual paths are always (on *all* platforms) POSIX. Therefore using path.posix here - const newResourceName = path.posix.basename(markdownResourcePath, ".md") + ".html"; - const newResourcePath = path.posix.join(path.posix.dirname(markdownResourcePath), newResourceName); - - const markdownResource = createResource({ - path: newResourcePath, - string: htmlString - }); - await workspace.write(markdownResource); - })); + let textResources; + + if (changedProjectResourcePaths) { + textResources = await Promise.all(changedProjectResourcePaths.map((resource) => workspace.byPath(resource))); + } else { + textResources = await workspace.byGlob("**/*.md"); + } + + await Promise.all(textResources.map(async (resource) => { + const markdownResourcePath = resource.getPath(); + + log.info(`Rendering markdown file ${markdownResourcePath}...`); + const htmlString = await renderMarkdown(await resource.getString(), options.configuration); + + // Note: @ui5/fs virtual paths are always (on *all* platforms) POSIX. Therefore using path.posix here + const newResourceName = path.posix.basename(markdownResourcePath, ".md") + ".html"; + const newResourcePath = path.posix.join(path.posix.dirname(markdownResourcePath), newResourceName); + + const markdownResource = createResource({ + path: newResourcePath, + string: htmlString + }); + await workspace.write(markdownResource); + })); }; + +export function supportsDifferentialBuilds() { + return true; +} ``` ```js [CommonJS] @@ -360,10 +406,17 @@ const renderMarkdown = require("./renderMarkdown.js"); /* * Render all .md (Markdown) files in the project to HTML */ -module.exports = async function({dependencies, log, options, taskUtil, workspace}) { +module.exports = async function({dependencies, log, options, taskUtil, workspace, changedProjectResourcePaths}) { const {createResource} = taskUtil.resourceFactory; - const textResources = await workspace.byGlob("**/*.md"); - await Promise.all(textResources.map(async (resource) => { + let textResources; + + if (changedProjectResourcePaths) { + textResources = await Promise.all(changedProjectResourcePaths.map((resource) => workspace.byPath(resource))); + } else { + textResources = await workspace.byGlob("**/*.md"); + } + + await Promise.all(textResources.map(async (resource) => { const markdownResourcePath = resource.getPath(); log.info(`Rendering markdown file ${markdownResourcePath}...`); @@ -380,6 +433,10 @@ module.exports = async function({dependencies, log, options, taskUtil, workspace await workspace.write(markdownResource); })); }; + +module.exports.supportsDifferentialBuilds = function() { + return true; +} ``` ::: diff --git a/internal/documentation/docs/updates/migrate-v5.md b/internal/documentation/docs/updates/migrate-v5.md index bcb8d74ceb3..2847d6f73e0 100644 --- a/internal/documentation/docs/updates/migrate-v5.md +++ b/internal/documentation/docs/updates/migrate-v5.md @@ -31,7 +31,7 @@ Projects using older **Specification Versions** are expected to be **fully compa ## Build Cache -UI5 CLI v5 introduces **builds with caching** for both commands `ui5 build` and `ui5 serve`. This fundamental architectural change significantly improves build performance by reusing cached results from previous builds. +UI5 CLI v5 introduces **builds with caching** for both commands `ui5 build` and `ui5 serve`. This fundamental architectural change significantly improves build performance by reusing cached results from previous builds and simplifies development with the Server by making most custom middleware obsolete. ### What Changed @@ -39,10 +39,12 @@ UI5 CLI v5 introduces **builds with caching** for both commands `ui5 build` and - Every source change resulted in an entire rebuild of all projects - Every build re-executed all tasks - No caching between builds or server sessions +- Custom middleware required for special actions **New Behavior (v5):** - Only relevant projects are rebuilt - Only modified resources and affected tasks are re-processed +- Custom middleware obsolete by replacing with build tasks ### Impact on Your Workflow @@ -61,13 +63,12 @@ If you plan to execute a build only once (e.g. during a CI run), consider using ### For `ui5 serve` -During a server session (started by `ui5 serve`), source changes are automatically being monitered. Then, if a request was made, the server detects this, tries to use caches and only rebuilds when none are available. For more information see [Watch Mode Behavior](../pages/Server.md#watch-mode-behavior). +The UI5 Server now performs a build of the project. When started with `ui5 serve`, a similar build to `ui5 build` is executed containing standard and custom tasks (see [exceptions](../pages/Server.md#standard-tasks)). -::: info Review custom middleware +During a server session, source changes are automatically being monitered. Then, if a request was made, the server detects this, tries to use caches and only rebuilds when none are available. For more information see [Watch Mode Behavior](../pages/Server.md#watch-mode-behavior). -With this feature, **build tasks are executed in server sessions**. For this reason, some custom middleware might be obsolete or cause problems. Projects utilizing such might need to adapt their configuration. - -E.g. Middleware for browser live reloads is obsolete and can be removed. Also, middleware for Typescript transpilation is not required anymore (as long as the respective task is still set up). +::: tip Review custom middleware +Due to **build tasks now being executed in server sessions**, custom middleware becomes obsolete if a corresponding task can perform the same actions (e.g. Typescript transpilation). However, custom middleware for non-build purposes such as proxies are not affected by this, and are still a valid use case. ::: ## Rename of Command Option @@ -251,13 +252,13 @@ The test suite is now served under the standard `/test-resources/` path with the The following middleware has been removed from the [standard middlewares list](../pages/Server.md#standard-middleware): -* `serveThemes` β€” Theme compilation (LESS to CSS) is now handled by the `buildThemes` build task during the incremental build, rather than on demand during runtime. The resulting CSS files are served via the `serveResources` middleware. This change improves performance through build-time compilation and caching while maintaining the same functionality. +* `serveThemes` β€” Theme compilation (LESS to CSS) is now handled by the `buildThemes` build task. Due to server sessions now also performing builds, this task gets executed during a server start, rather than on demand during runtime. The resulting CSS files are served via the `serveResources` middleware. This change improves performance through build-time compilation and caching while maintaining the same functionality. **Backward Compatibility:** If your project or any custom middleware references a removed middleware via `beforeMiddleware` or `afterMiddleware`, UI5 CLI will automatically remap the reference to the nearest remaining middleware and log a deprecation warning. Your custom middleware will still be executed in the expected order. **What Changed:** -- Theme CSS files (`library.css`, `library-RTL.css`, etc.) are now **pre-built** during the incremental build +- Theme CSS files (`library.css`, `library-RTL.css`, etc.) are now **pre-built** - Files are served via `serveResources` instead of being compiled on demand - The same CSS files are available at the same URLs as before From 0bcf4d60d5f10c28cf13cfb01988e5bde354a167 Mon Sep 17 00:00:00 2001 From: Max Reichmann <91143102+maxreichmann@users.noreply.github.com> Date: Thu, 18 Jun 2026 12:46:57 +0200 Subject: [PATCH 4/5] refactor: Address @KlattG review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ⚠️ one discussion open in `migrate-v5.md` Co-authored-by: GΓΌnter Klatt --- internal/documentation/docs/pages/Builder.md | 2 +- internal/documentation/docs/pages/Server.md | 6 +++--- .../docs/pages/extensibility/CustomTasks.md | 14 +++++++------- .../documentation/docs/updates/migrate-v5.md | 16 ++++++++-------- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/internal/documentation/docs/pages/Builder.md b/internal/documentation/docs/pages/Builder.md index f3bf7d36cb4..aa01c59979a 100644 --- a/internal/documentation/docs/pages/Builder.md +++ b/internal/documentation/docs/pages/Builder.md @@ -215,7 +215,7 @@ Example: ```sh ui5 build --cache Off ``` -In this scenario, when a source file change is made, always perform a full rebuild (even if this source version already existed sometime ago). +In this scenario, when a source file is changed, always perform a full rebuild, even if this source version existed previously. ::: info By default, the build cache is stored inside UI5 CLI's Data Dir (`~/.ui5/buildCache/`). You can customize the location (see [Changing UI5 CLI's Data Directory](./Troubleshooting#changing-ui5-cli-s-data-directory)). diff --git a/internal/documentation/docs/pages/Server.md b/internal/documentation/docs/pages/Server.md index 61ed43e118e..a502b696b2e 100644 --- a/internal/documentation/docs/pages/Server.md +++ b/internal/documentation/docs/pages/Server.md @@ -88,7 +88,7 @@ Answers all non-read requests (POST, PUT, DELETE, etc.) that have not been answe In case a directory has been requested, this middleware renders an HTML with a list of the directory's content. ## Standard Tasks -As with the UI5 Builder, a set of standard tasks is being executed during a server build. However, following tasks are being **excluded by default**: +As with the UI5 Builder, a set of standard tasks is being executed during a server build. However, the following tasks are being **excluded by default**: - `minify` - `generateLibraryPreload` - `generateComponentPreload` @@ -113,7 +113,7 @@ Example: ```sh ui5 serve --cache Off ``` -In this scenario, when a source file change is made and a request comes in, the server always performs a full rebuild (even if this source version already existed sometime ago). +In this scenario, when a source file changes and a request comes in, the server always performs a full rebuild, even if this source version existed previously. ::: info By default, build caches created by `ui5 build` and `ui5 serve` are **separate and cannot be mixed**. Each command executes a distinct set of tasks, resulting in separate caches tailored to its specific use case. For more details on builder caching, see the [UI5 Builder documentation](./Builder.md). @@ -121,7 +121,7 @@ By default, build caches created by `ui5 build` and `ui5 serve` are **separate a ### Watch Mode Behavior -Once started with `ui5 serve`, the server automatically keeps watch over changes to the source files throughout the session. When a request arrives, it checks for cached results first and only triggers a rebuild of the respective resources and tasks if no cache is available. +Once started with `ui5 serve`, the server automatically monitors changes to the source files throughout the session. When a request arrives, it checks for cached results first and only triggers a rebuild of the respective resources and tasks if no cache is available. - **Monitored files**: All files in your project's source directories (`src/`, `webapp/`, `test/`, etc.) - **Not monitored**: Configuration files (`ui5.yaml`, `package.json`), custom task implementations, and dependency files diff --git a/internal/documentation/docs/pages/extensibility/CustomTasks.md b/internal/documentation/docs/pages/extensibility/CustomTasks.md index ac78deca51f..be10565bf20 100644 --- a/internal/documentation/docs/pages/extensibility/CustomTasks.md +++ b/internal/documentation/docs/pages/extensibility/CustomTasks.md @@ -130,11 +130,11 @@ A custom task implementation needs to return a function with the following signa * Custom task configuration, as defined in the project's ui5.yaml * @param {string[] | undefined} parameters.changedProjectResourcePaths * List of changed resource paths since last execution. - * Only use if the task supports differential builds (supportsDifferentialBuilds=true). + * Only used if the task supports differential builds (supportsDifferentialBuilds=true). * Returns undefined if unsupported or no cache is available. * @param {string[] | undefined} parameters.changedDependencyResourcePaths * List of changed dependency resource paths since last execution. - * Only use if the task supports differential builds (supportsDifferentialBuilds=true). + * Only used if the task supports differential builds (supportsDifferentialBuilds=true). * Returns undefined if unsupported or no cache is available. * @param {string} parameters.options.taskName * Name of the custom task. @@ -176,11 +176,11 @@ export default async function({dependencies, log, options, taskUtil, workspace}) * Custom task configuration, as defined in the project's ui5.yaml * @param {string[] | undefined} parameters.changedProjectResourcePaths * List of changed resource paths since last execution. - * Only use if the task supports differential builds (supportsDifferentialBuilds=true). + * Only used if the task supports differential builds (supportsDifferentialBuilds=true). * Returns undefined if unsupported or no cache is available. * @param {string[] | undefined} parameters.changedDependencyResourcePaths * List of changed dependency resource paths since last execution. - * Only use if the task supports differential builds (supportsDifferentialBuilds=true). + * Only used if the task supports differential builds (supportsDifferentialBuilds=true). * Returns undefined if unsupported or no cache is available. * @param {string} parameters.options.taskName * Name of the custom task. @@ -304,7 +304,7 @@ module.exports.determineRequiredDependencies = async function({availableDependen ### "Cache-aware" Tasks -Due to UI5 Builder and UI5 Server supporting **build caches** of task data, custom tasks can opt into this behavior to improve performance. This is done by exporting optional callback functions in your task implementation: +Due to UI5 Builder and UI5 Server supporting **build caches** of task data, custom tasks can opt into this behavior to improve performance. To do this, export optional callback functions in your task implementation: #### `supportsDifferentialBuilds()` @@ -339,7 +339,7 @@ module.exports.supportsDifferentialBuilds = function() { } ``` -When this returns `true`, your task's main function receives an additional parameter `changedProjectResourcePaths` providing an array of changed resource paths (strings) since its last execution. The task can then process only those resources instead of all resources. If this callback is not provided (or it returns a falsy value), your task will not be able to use incremental cache invalidation and processes all resources from scratch. +When this returns `true`, your task's main function receives an additional parameter `changedProjectResourcePaths`. This parameter provides an array of changed resource paths (strings) since its last execution. The task then processes only those resources instead of all resources. If this callback isn't provided or returns a falsy value, your task can't use incremental cache invalidation and processes all resources from scratch. ::: info Best Practices for Cache-aware Tasks 1. **Keep tasks deterministic**: Given the same inputs, always produce the same outputs @@ -355,7 +355,7 @@ The following code snippets show examples for custom task implementations. This example is making use of the `resourceFactory` [TaskUtil](https://ui5.github.io/cli/v5/api/@ui5_project_build_helpers_TaskUtil.html) API to create new resources based on the output of a third-party module for rendering Markdown files. The created resources are added to the build result by writing them into the provided `workspace`. -In addition, differential builds are supported by this task which re-processes only changed resources. +In addition, this task supports differential builds, which re-process only changed resources. ::: code-group diff --git a/internal/documentation/docs/updates/migrate-v5.md b/internal/documentation/docs/updates/migrate-v5.md index 2847d6f73e0..452a00981b2 100644 --- a/internal/documentation/docs/updates/migrate-v5.md +++ b/internal/documentation/docs/updates/migrate-v5.md @@ -31,15 +31,15 @@ Projects using older **Specification Versions** are expected to be **fully compa ## Build Cache -UI5 CLI v5 introduces **builds with caching** for both commands `ui5 build` and `ui5 serve`. This fundamental architectural change significantly improves build performance by reusing cached results from previous builds and simplifies development with the Server by making most custom middleware obsolete. +UI5 CLI v5 introduces **builds with caching** for both the `ui5 build` and `ui5 serve` commands. This fundamental architectural change significantly improves build performance by reusing cached results from previous builds. It also simplifies development with the server by making most custom middleware obsolete. ### What Changed **Previous Behavior (v4 and earlier):** -- Every source change resulted in an entire rebuild of all projects +- Every source change resulted in a full rebuild of all projects - Every build re-executed all tasks - No caching between builds or server sessions -- Custom middleware required for special actions +- Custom middleware was required for special actions **New Behavior (v5):** - Only relevant projects are rebuilt @@ -48,7 +48,7 @@ UI5 CLI v5 introduces **builds with caching** for both commands `ui5 build` and ### Impact on Your Workflow -- **First build**: Probably slightly slower, as the cache is populated with all build outputs +- **First build**: Probably slightly slower as the cache is populated with all build outputs - **Subsequent builds**: Significantly faster β€” only modified resources and affected tasks are reprocessed - **Quick iterations**: Changes to individual files typically rebuild very quickly - **Cross-session**: Caches are used between server restarts and build runs @@ -58,17 +58,17 @@ UI5 CLI v5 introduces **builds with caching** for both commands `ui5 build` and When `ui5 build` is executed, build caches are automatically serialized and reused when available. ::: tip Tip for Single Builds (e.g. CI/CD) -If you plan to execute a build only once (e.g. during a CI run), consider using `--cache "Off"` (see [Build Cache Control](../pages/Builder.md#build-cache-control)) to skip cache serialization. +If you plan to execute a build only once (for example during a CI run), consider using `--cache "Off"` (see [Build Cache Control](../pages/Builder.md#build-cache-control)) to skip cache serialization. ::: ### For `ui5 serve` The UI5 Server now performs a build of the project. When started with `ui5 serve`, a similar build to `ui5 build` is executed containing standard and custom tasks (see [exceptions](../pages/Server.md#standard-tasks)). -During a server session, source changes are automatically being monitered. Then, if a request was made, the server detects this, tries to use caches and only rebuilds when none are available. For more information see [Watch Mode Behavior](../pages/Server.md#watch-mode-behavior). +During a server session, source changes are automatically monitored. When a request is made, the server detects this, tries to use caches, and only rebuilds when none are available. For more information, see [Watch Mode Behavior](../pages/Server.md#watch-mode-behavior). ::: tip Review custom middleware -Due to **build tasks now being executed in server sessions**, custom middleware becomes obsolete if a corresponding task can perform the same actions (e.g. Typescript transpilation). However, custom middleware for non-build purposes such as proxies are not affected by this, and are still a valid use case. +Due to **build tasks now being executed in server sessions**, custom middleware becomes obsolete if a corresponding task can perform the same actions (for example, Typescript transpilation). However, custom middleware for non-build purposes, such as proxies, are not affected by this and are still a valid use case. ::: ## Rename of Command Option @@ -252,7 +252,7 @@ The test suite is now served under the standard `/test-resources/` path with the The following middleware has been removed from the [standard middlewares list](../pages/Server.md#standard-middleware): -* `serveThemes` β€” Theme compilation (LESS to CSS) is now handled by the `buildThemes` build task. Due to server sessions now also performing builds, this task gets executed during a server start, rather than on demand during runtime. The resulting CSS files are served via the `serveResources` middleware. This change improves performance through build-time compilation and caching while maintaining the same functionality. +* `serveThemes` β€” The `buildThemes` build task now handles theme compilation (LESS to CSS). Because server sessions now also perform builds, this task runs during a server start instead of on demand during runtime. The resulting CSS files are served by the `serveResources` middleware. This change improves performance through build-time compilation and caching while maintaining the same functionality. **Backward Compatibility:** If your project or any custom middleware references a removed middleware via `beforeMiddleware` or `afterMiddleware`, UI5 CLI will automatically remap the reference to the nearest remaining middleware and log a deprecation warning. Your custom middleware will still be executed in the expected order. From 1ebfcbd3c131c82396b47576134e799fd7010dba Mon Sep 17 00:00:00 2001 From: Max Reichmann <91143102+maxreichmann@users.noreply.github.com> Date: Thu, 18 Jun 2026 13:51:05 +0200 Subject: [PATCH 5/5] refactor: Apply suggestion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: GΓΌnter Klatt --- internal/documentation/docs/updates/migrate-v5.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/documentation/docs/updates/migrate-v5.md b/internal/documentation/docs/updates/migrate-v5.md index 452a00981b2..11cf28d1ba5 100644 --- a/internal/documentation/docs/updates/migrate-v5.md +++ b/internal/documentation/docs/updates/migrate-v5.md @@ -44,7 +44,7 @@ UI5 CLI v5 introduces **builds with caching** for both the `ui5 build` and `ui5 **New Behavior (v5):** - Only relevant projects are rebuilt - Only modified resources and affected tasks are re-processed -- Custom middleware obsolete by replacing with build tasks +- Some custom middleware is now obsolete as it can be replaced with build tasks ### Impact on Your Workflow