Skip to content
Merged
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
5 changes: 3 additions & 2 deletions internal/documentation/docs/pages/Builder.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ All available standard tasks are documented under **API -> @ui5/builder -> tasks
| [executeJsdocSdkTransformation](../api/module-@ui5_builder_tasks_jsdoc_executeJsdocSdkTransformation) | | | *disabled* <sup>1</sup> | |
| [minify](../api/module-@ui5_builder_tasks_minify) | enabled | enabled | enabled | |
| [generateFlexChangesBundle](../api/module-@ui5_builder_tasks_bundlers_generateFlexChangesBundle) | enabled | enabled | enabled | |
| [generateLibraryManifest](../api/module-@ui5_builder_tasks_generateLibraryManifest) | | | enabled | |
| [generateLibraryManifest](../api/module-@ui5_builder_tasks_generateLibraryManifest) | | | *disabled* <sup>7</sup> | |
| [enhanceManifest](../api/module-@ui5_builder_tasks_enhanceManifest) | enabled | enabled | enabled | |
| [generateComponentPreload](../api/module-@ui5_builder_tasks_bundlers_generateComponentPreload) | enabled | enabled | *disabled* <sup>2</sup> | |
| [generateLibraryPreload](../api/module-@ui5_builder_tasks_bundlers_generateLibraryPreload) | | | enabled | |
Expand All @@ -58,7 +58,8 @@ All available standard tasks are documented under **API -> @ui5/builder -> tasks
<sup>3</sup> Enabled in `self-contained` build, which disables `generateComponentPreload` and `generateLibraryPreload`
<sup>4</sup> Enabled for projects defining a [bundle configuration](./Configuration.md#custom-bundling)
<sup>5</sup> Can be enabled for framework projects via the `includeTask` option. For other projects, this task is skipped
<sup>6</sup> Disabled for the server due to a corresponding middleware producing the same output
<sup>6</sup> Disabled for the server due to a corresponding middleware producing the same output
<sup>7</sup> Enabled for Specification Version 4.0 and lower, and for framework projects. For other projects using Specification Version 5.0 and higher, this task is skipped

### minify

Expand Down
4 changes: 4 additions & 0 deletions internal/documentation/docs/pages/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -812,6 +812,10 @@ Version | UI5 CLI Release

### Specification Version 5.0

**Breaking changes:**

- The `generateLibraryManifest` build task is no longer executed for projects of type `library`. SAPUI5 distribution libraries (framework projects) are not affected. Libraries must provide a `manifest.json` directly in their source directory. See [Migrate to v5: generateLibraryManifest Task No Longer Executed](../updates/migrate-v5.md#generatelibrarymanifest-task-no-longer-executed) for details.

**Features:**

- Adds support for the new [`component`](./Project.md#component) project type for developing UI5 components — including application, reusable UI, and faceless components — which, unlike `application`-type projects, are served under their own namespace so multiple can coexist in one environment
Expand Down
17 changes: 17 additions & 0 deletions internal/documentation/docs/updates/migrate-v5.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,23 @@ 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**.

## generateLibraryManifest Task No Longer Executed
Comment thread
d3xter666 marked this conversation as resolved.

::: info Specification Version 5.0 only
This change only applies to library projects that upgrade their `specVersion` to `5.0` in `ui5.yaml`. Projects on **Specification Version 4.0 and lower are not affected**. **SAPUI5 distribution libraries (framework projects) are not affected**.
:::

With **Specification Version 5.0**, the [`generateLibraryManifest`](../api/module-@ui5_builder_tasks_generateLibraryManifest) build task is no longer executed for non-framework library projects. Libraries must provide a `manifest.json` directly in their source directory.
Comment thread
d3xter666 marked this conversation as resolved.

**Action required** when upgrading a library project to Specification Version 5.0:

- Ensure your library has a `manifest.json` in its source directory. A previously auto-generated one is fully compatible and can be reused as-is.
- If no `manifest.json` is present, any UI5 CLI command that resolves the project graph (such as `ui5 build`, `ui5 serve`, or `ui5 tree`) will fail with a descriptive error and a link to this migration guide.

::: tip
To see which standard tasks are executed for each project type, check out the [Standard Tasks](../pages/Builder#standard-tasks) table in the UI5 Builder page.
:::

## Build Cache

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.
Expand Down
7 changes: 6 additions & 1 deletion packages/project/lib/build/definitions/library.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,12 @@ export default function({project, taskUtil, getTask}) {
}
});

tasks.set("generateLibraryManifest", {});
// For specVersion 5.0+, only execute for framework libraries
if (project.getSpecVersion().lt("5.0") || project.isFrameworkProject()) {
tasks.set("generateLibraryManifest", {});
} else {
tasks.set("generateLibraryManifest", {taskFunction: null});
Comment thread
matz3 marked this conversation as resolved.
}

tasks.set("enhanceManifest", {});

Expand Down
19 changes: 16 additions & 3 deletions packages/project/lib/specifications/types/Library.js
Original file line number Diff line number Diff line change
Expand Up @@ -391,9 +391,22 @@ class Library extends ComponentProject {
`at ${filePath}`);
}
} catch (err) {
this._log.verbose(
`Namespace resolution from manifest.json failed for project ` +
`${this.getName()}: ${err.message}`);
// For Specification Version 5.0+, non-framework libraries must provide a manifest.json
if (this.getSpecVersion().gte("5.0") && !this.isFrameworkProject()) {
throw new Error(
`Could not find required manifest.json for library project ${this.getName()}: ` +
`${err.message}\n\n` +
`Library projects using Specification Version 5.0 or higher must provide ` +
`a manifest.json directly in their source directory.\n` +
`For migration details, please refer to:\n` +
`https://ui5.github.io/cli/updates/migrate-v5/#generatelibrarymanifest-task-no-longer-executed`, {
Comment thread
d3xter666 marked this conversation as resolved.
cause: err
});
} else {
this._log.verbose(
`Namespace resolution from manifest.json failed for project ` +
`${this.getName()}: ${err.message}`);
}
}
return {};
}
Expand Down
7 changes: 7 additions & 0 deletions packages/project/test/lib/build/ProjectBuilder.integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -1624,6 +1624,11 @@ test.serial("Build library.d (Custom Library preload configuration)", async (t)
// This custom preload configuration generates a library-preload.js similar to a default one.
// However, it will omit a resource ("some.js") from the bundle.

// ui5-custom-preload-config.yaml uses specVersion 5.0, which requires a manifest.json
await fixtureTester._initialize();
await fs.writeFile(`${fixtureTester.fixturePath}/main/src/library/d/manifest.json`,
JSON.stringify({"sap.app": {"id": "library.d", "type": "library"}}, null, "\t"));

// #1 build (no cache, no changes)
await fixtureTester.buildProject({
graphConfig: {rootConfigPath: "ui5-custom-preload-config.yaml"},
Expand Down Expand Up @@ -3064,6 +3069,8 @@ sap.ui.define([
};
return thisLib;
});`);
await fs.writeFile(`${this.fixturePath}/node_modules/library.z/src/library/z/manifest.json`,
JSON.stringify({"sap.app": {"id": "library.z", "type": "library"}}, null, "\t"));
await fs.writeFile(`${this.fixturePath}/node_modules/library.z/src/library/z/.library`,
`<?xml version="1.0" encoding="UTF-8" ?>
<library xmlns="http://www.sap.com/sap.ui.library.xsd" >
Expand Down
3 changes: 2 additions & 1 deletion packages/project/test/lib/build/TaskRunner.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ function getMockProject(type) {
getMinificationExcludes: emptyarray,
getSpecVersion: () => {
return {
gte: () => false
gte: () => false,
lt: () => true
};
},
getComponentPreloadPaths: () => [
Expand Down
45 changes: 42 additions & 3 deletions packages/project/test/lib/build/definitions/library.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ function getMockProject() {
getSpecVersion: () => {
return {
toString: () => "2.6",
gte: () => true
gte: () => true,
lt: () => true
};
},
getMinificationExcludes: emptyarray,
Expand Down Expand Up @@ -187,7 +188,8 @@ test("Standard build with legacy spec version", (t) => {
project.getSpecVersion = () => {
return {
toString: () => "0.1",
gte: () => false
gte: () => false,
lt: () => true
};
};

Expand Down Expand Up @@ -507,7 +509,8 @@ test("Minification excludes not applied for legacy specVersion", (t) => {
project.getSpecVersion = () => {
return {
toString: () => "2.5",
gte: () => false
gte: () => false,
lt: () => true
};
};
project.getMinificationExcludes = () => ["**.html"];
Expand Down Expand Up @@ -639,6 +642,42 @@ test("buildThemes: Project is not root", (t) => {
}
}, "Correct buildThemes task definition");
});
test("generateLibraryManifest: specVersion 5.0, non-framework project", (t) => {
const {project, taskUtil, getTask} = t.context;

project.getSpecVersion = () => {
return {
toString: () => "5.0",
gte: () => true,
lt: () => false
};
};
project.isFrameworkProject = () => false;

const tasks = library({project, taskUtil, getTask});

t.deepEqual(tasks.get("generateLibraryManifest"), {taskFunction: null},
"generateLibraryManifest is skipped for non-framework libraries on specVersion 5.0");
});

test("generateLibraryManifest: specVersion 5.0, framework project", (t) => {
const {project, taskUtil, getTask} = t.context;

project.getSpecVersion = () => {
return {
toString: () => "5.0",
gte: () => true,
lt: () => false
};
};
project.isFrameworkProject = () => true;

const tasks = library({project, taskUtil, getTask});

t.deepEqual(tasks.get("generateLibraryManifest"), {},
"generateLibraryManifest runs for framework libraries on specVersion 5.0");
});

test("buildThemes: CSS Variables enabled", (t) => {
const {project, taskUtil, getTask} = t.context;
taskUtil.getBuildOption.returns(true);
Expand Down
42 changes: 42 additions & 0 deletions packages/project/test/lib/specifications/types/Library.js
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,48 @@ test.serial("_parseConfiguration: No preload exclude fallback for non-framework
t.is(getPreloadExcludesFromDotLibraryStub.callCount, 0, "_getPreloadExcludesFromDotLibrary has not been called");
});

test.serial("_parseConfiguration: Missing manifest.json throws for specVersion 5.0 non-framework library",
async (t) => {
const {projectInput, sinon} = t.context;
projectInput.configuration.specVersion = "5.0";

sinon.stub(Library.prototype, "isFrameworkProject").returns(false);
sinon.stub(Library.prototype, "_getManifest").rejects(
new Error("Could not find manifest.json file for project library.d"));

const error = await t.throwsAsync(new Library().init(projectInput));

t.true(error.message.includes("Could not find required manifest.json for library project library.d"),
"Error message mentions missing manifest.json");
t.true(error.message.includes("migrate-v5"),
"Error message references the migration guide");
});

test.serial("_parseConfiguration: Missing manifest.json is allowed for specVersion 5.0 framework library",
async (t) => {
const {projectInput, sinon} = t.context;
projectInput.configuration.specVersion = "5.0";

sinon.stub(Library.prototype, "isFrameworkProject").returns(true);
sinon.stub(Library.prototype, "_getManifest").rejects(
new Error("Could not find manifest.json file for project library.d"));

await t.notThrowsAsync(new Library().init(projectInput),
"No error thrown for framework library without manifest.json");
});

test.serial("_parseConfiguration: Missing manifest.json is allowed for specVersion 4.0 library", async (t) => {
const {projectInput, sinon} = t.context;
projectInput.configuration.specVersion = "4.0";

sinon.stub(Library.prototype, "isFrameworkProject").returns(false);
sinon.stub(Library.prototype, "_getManifest").rejects(
new Error("Could not find manifest.json file for project library.d"));

await t.notThrowsAsync(new Library().init(projectInput),
"No error thrown for specVersion 4.0 library without manifest.json");
});

test("_getManifest: Reads correctly", async (t) => {
const {projectInput, sinon} = t.context;

Expand Down
Loading