Skip to content

Commit

Permalink
[FEATURE] Bundle 'require' section with async flag for specVersion: 4…
Browse files Browse the repository at this point in the history
….0 (#1042)

JIRA: CPOUI5FOUNDATION-835

This change completes #1033 with
check for specVersion: 4.0 and enforcing default async flag for require
section in 'bundleDefinitions'

---------

Co-authored-by: Merlin Beutlberger <m.beutlberger@sap.com>
  • Loading branch information
d3xter666 and RandomByte authored Jul 5, 2024
1 parent 934956a commit dfa67fe
Show file tree
Hide file tree
Showing 10 changed files with 465 additions and 169 deletions.
10 changes: 2 additions & 8 deletions lib/processors/bundlers/moduleBundler.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ const log = getLogger("builder:processors:bundlers:moduleBundler");
* @param {string} [parameters.options.targetUi5CoreVersion] Optional semver compliant sap.ui.core project version, e.g '2.0.0'.
This allows the bundler to make assumptions on available runtime APIs.
Omit if the ultimate UI5 version at runtime is unknown or can't be determined.
* @param {@ui5/project/build/helpers/TaskUtil|object} [parameters.taskUtil] TaskUtil
* @returns {Promise<module:@ui5/builder/processors/bundlers/moduleBundler~ModuleBundlerResult[]>}
* Promise resolving with module bundle resources
*/
Expand All @@ -152,14 +153,7 @@ export default function({resources, options: {
ignoreMissingModules: false
}, bundleOptions);

// Apply defaults without modifying the passed object
bundleDefinition = Object.assign({
resolve: false,
resolveConditional: false,
renderer: false,
sort: true,
declareRawModules: false,
}, bundleDefinition);
// bundleDefinition's defaults get applied in the corresponding standard tasks

const pool = new LocatorResourcePool({
ignoreMissingModules: bundleOptions.ignoreMissingModules
Expand Down
5 changes: 4 additions & 1 deletion lib/tasks/bundlers/generateBundle.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import moduleBundler from "../../processors/bundlers/moduleBundler.js";
import {applyDefaultsToBundleDefinition} from "./utils/applyDefaultsToBundleDefinition.js";
import createModuleNameMapping from "./utils/createModuleNameMapping.js";
import ReaderCollectionPrioritized from "@ui5/fs/ReaderCollectionPrioritized";

Expand Down Expand Up @@ -96,7 +97,9 @@ export default async function({
}
const coreVersion = taskUtil?.getProject("sap.ui.core")?.getVersion();
return combo.byGlob("/resources/**/*.{js,json,xml,html,properties,library,js.map}").then((resources) => {
const options = {bundleDefinition, bundleOptions};
const options = {
bundleDefinition: applyDefaultsToBundleDefinition(bundleDefinition, taskUtil), bundleOptions
};
if (!optimize && taskUtil) {
options.moduleNameMapping = createModuleNameMapping({resources, taskUtil});
}
Expand Down
3 changes: 2 additions & 1 deletion lib/tasks/bundlers/generateComponentPreload.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import path from "node:path";
import moduleBundler from "../../processors/bundlers/moduleBundler.js";
import {applyDefaultsToBundleDefinition} from "./utils/applyDefaultsToBundleDefinition.js";
import {getLogger} from "@ui5/logger";
const log = getLogger("builder:tasks:bundlers:generateComponentPreload");
import {negateFilters} from "../../lbt/resources/ResourceFilterList.js";
Expand Down Expand Up @@ -148,7 +149,7 @@ export default async function({
return Promise.all(bundleDefinitions.filter(Boolean).map((bundleDefinition) => {
log.verbose(`Generating ${bundleDefinition.name}...`);
const options = {
bundleDefinition,
bundleDefinition: applyDefaultsToBundleDefinition(bundleDefinition, taskUtil),
bundleOptions: {
ignoreMissingModules: true,
optimize: true
Expand Down
2 changes: 2 additions & 0 deletions lib/tasks/bundlers/generateLibraryPreload.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {getLogger} from "@ui5/logger";
const log = getLogger("builder:tasks:bundlers:generateLibraryPreload");
import moduleBundler from "../../processors/bundlers/moduleBundler.js";
import {applyDefaultsToBundleDefinition} from "./utils/applyDefaultsToBundleDefinition.js";
import {negateFilters} from "../../lbt/resources/ResourceFilterList.js";
import createModuleNameMapping from "./utils/createModuleNameMapping.js";

Expand Down Expand Up @@ -265,6 +266,7 @@ export default async function({workspace, taskUtil, options: {skipBundles = [],
if (coreVersion) {
options.targetUi5CoreVersion = coreVersion;
}
options.bundleDefinition = applyDefaultsToBundleDefinition(options.bundleDefinition, taskUtil);
return moduleBundler({options, resources});
};

Expand Down
33 changes: 20 additions & 13 deletions lib/tasks/bundlers/generateStandaloneAppBundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {getLogger} from "@ui5/logger";
const log = getLogger("builder:tasks:bundlers:generateStandaloneAppBundle");
import ReaderCollectionPrioritized from "@ui5/fs/ReaderCollectionPrioritized";
import moduleBundler from "../../processors/bundlers/moduleBundler.js";
import {applyDefaultsToBundleDefinition} from "./utils/applyDefaultsToBundleDefinition.js";
import createModuleNameMapping from "./utils/createModuleNameMapping.js";

function getBundleDefinition(config) {
Expand Down Expand Up @@ -139,24 +140,30 @@ export default async function({workspace, dependencies, taskUtil, options}) {
}

const bundleOptions = {
bundleDefinition: getBundleDefinition({
name: "sap-ui-custom.js",
filters,
namespace,
preloadSection: true
})
bundleDefinition: applyDefaultsToBundleDefinition(
getBundleDefinition({
name: "sap-ui-custom.js",
filters,
namespace,
preloadSection: true,
}),
taskUtil
),
};

const bundleDbgOptions = {
bundleDefinition: getBundleDefinition({
name: "sap-ui-custom-dbg.js",
filters,
namespace
}),
bundleDefinition: applyDefaultsToBundleDefinition(
getBundleDefinition({
name: "sap-ui-custom-dbg.js",
filters,
namespace,
}),
taskUtil
),
bundleOptions: {
optimize: false
optimize: false,
},
moduleNameMapping: unoptimizedModuleNameMapping
moduleNameMapping: unoptimizedModuleNameMapping,
};

if (coreVersion) {
Expand Down
31 changes: 31 additions & 0 deletions lib/tasks/bundlers/utils/applyDefaultsToBundleDefinition.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* Applies default values to bundleDefinitions
*
* @param {module:@ui5/builder/processors/bundlers/moduleBundler~ModuleBundleDefinition} bundleDefinition Module
* bundle definition
* @param {@ui5/project/build/helpers/TaskUtil|object} [taskUtil] TaskUtil
*
* @returns {module:@ui5/builder/processors/bundlers/moduleBundler~ModuleBundleDefinition}
*/
export function applyDefaultsToBundleDefinition(bundleDefinition, taskUtil) {
bundleDefinition.sections = bundleDefinition?.sections?.map((section) => {
const defaultValues = {
resolve: false,
resolveConditional: false,
renderer: false,
sort: true,
declareRawModules: false,
};

// Since specVersion: 4.0 "require" section starts loading asynchronously.
// If specVersion cannot be determined, the latest spec is taken into account.
// This is a breaking change in specVersion: 4.0
if (section.mode === "require" && (!taskUtil || taskUtil.getProject().getSpecVersion().gte("4.0"))) {
defaultValues.async = true;
}

return Object.assign(defaultValues, section);
});

return bundleDefinition;
}
88 changes: 7 additions & 81 deletions test/lib/processors/bundlers/moduleBundler.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,6 @@ test.serial("Builder returns single bundle", async (t) => {
const bundleOptions = {
"some": "option"
};
const effectiveBundleDefinition = {
// Defaults
"resolve": false,
"resolveConditional": false,
"renderer": false,
"sort": true,
"declareRawModules": false,

"some": "definition"
};

const createdBundle = {
name: "BundleName.js",
Expand Down Expand Up @@ -103,7 +93,7 @@ test.serial("Builder returns single bundle", async (t) => {

t.is(builder.createBundle.callCount, 1, "builder.createBundle should be called once");
t.is(builder.createBundle.getCall(0).args.length, 2);
t.deepEqual(builder.createBundle.getCall(0).args[0], effectiveBundleDefinition,
t.deepEqual(builder.createBundle.getCall(0).args[0], bundleDefinition,
"builder.createBundle should be called with bundleDefinition");
t.deepEqual(builder.createBundle.getCall(0).args[1], {
// default bundleOptions
Expand Down Expand Up @@ -143,17 +133,6 @@ test.serial("Builder returns multiple bundles", async (t) => {
"some": "option"
};

const effectiveBundleDefinition = {
// Defaults
"resolve": false,
"resolveConditional": false,
"renderer": false,
"sort": true,
"declareRawModules": false,

"some": "definition"
};

const createdBundles = [
{
name: "BundleName1.js",
Expand Down Expand Up @@ -226,7 +205,7 @@ test.serial("Builder returns multiple bundles", async (t) => {

t.is(builder.createBundle.callCount, 1, "builder.createBundle should be called once");
t.is(builder.createBundle.getCall(0).args.length, 2);
t.deepEqual(builder.createBundle.getCall(0).args[0], effectiveBundleDefinition,
t.deepEqual(builder.createBundle.getCall(0).args[0], bundleDefinition,
"builder.createBundle should be called with bundleDefinition");
t.deepEqual(builder.createBundle.getCall(0).args[1], {
// default bundleOptions
Expand Down Expand Up @@ -268,16 +247,6 @@ test.serial("bundleOptions default (no options passed)", async (t) => {
const bundleDefinition = {
"some": "definition"
};
const effectiveBundleDefinition = {
// Defaults
"resolve": false,
"resolveConditional": false,
"renderer": false,
"sort": true,
"declareRawModules": false,

"some": "definition"
};

const createdBundle = {
name: "BundleName.js",
Expand Down Expand Up @@ -325,7 +294,7 @@ test.serial("bundleOptions default (no options passed)", async (t) => {

t.is(builder.createBundle.callCount, 1, "builder.createBundle should be called once");
t.is(builder.createBundle.getCall(0).args.length, 2);
t.deepEqual(builder.createBundle.getCall(0).args[0], effectiveBundleDefinition,
t.deepEqual(builder.createBundle.getCall(0).args[0], bundleDefinition,
"builder.createBundle should be called with bundleDefinition");
t.deepEqual(builder.createBundle.getCall(0).args[1], {
// default bundleOptions
Expand Down Expand Up @@ -361,17 +330,6 @@ test.serial("bundleOptions default (empty options passed)", async (t) => {
};
const bundleOptions = {};

const effectiveBundleDefinition = {
// Defaults
"resolve": false,
"resolveConditional": false,
"renderer": false,
"sort": true,
"declareRawModules": false,

"some": "definition"
};

const createdBundle = {
name: "BundleName.js",
content: "Bundle Content",
Expand Down Expand Up @@ -400,7 +358,7 @@ test.serial("bundleOptions default (empty options passed)", async (t) => {

t.is(builder.createBundle.callCount, 1, "builder.createBundle should be called once");
t.is(builder.createBundle.getCall(0).args.length, 2);
t.deepEqual(builder.createBundle.getCall(0).args[0], effectiveBundleDefinition,
t.deepEqual(builder.createBundle.getCall(0).args[0], bundleDefinition,
"builder.createBundle should be called with bundleDefinition");
t.deepEqual(builder.createBundle.getCall(0).args[1], {
// default bundleOptions
Expand Down Expand Up @@ -434,17 +392,6 @@ test.serial("bundleOptions (all options passed)", async (t) => {
ignoreMissingModules: true
};

const effectiveBundleDefinition = {
// Defaults
"resolve": false,
"resolveConditional": false,
"renderer": false,
"sort": true,
"declareRawModules": false,

"some": "definition"
};

const createdBundle = {
name: "BundleName.js",
content: "Bundle Content",
Expand Down Expand Up @@ -473,7 +420,7 @@ test.serial("bundleOptions (all options passed)", async (t) => {

t.is(builder.createBundle.callCount, 1, "builder.createBundle should be called once");
t.is(builder.createBundle.getCall(0).args.length, 2);
t.deepEqual(builder.createBundle.getCall(0).args[0], effectiveBundleDefinition,
t.deepEqual(builder.createBundle.getCall(0).args[0], bundleDefinition,
"builder.createBundle should be called with bundleDefinition");
t.deepEqual(builder.createBundle.getCall(0).args[1], bundleOptions,
"builder.createBundle should be called with bundleOptions");
Expand Down Expand Up @@ -502,16 +449,6 @@ test.serial("Passes ignoreMissingModules bundleOption to LocatorResourcePool", a

"ignoreMissingModules": "foo"
};
const effectiveBundleDefinition = {
// Defaults
"resolve": false,
"resolveConditional": false,
"renderer": false,
"sort": true,
"declareRawModules": false,

"some": "definition"
};

const createdBundle = {
name: "BundleName.js",
Expand Down Expand Up @@ -560,7 +497,7 @@ test.serial("Passes ignoreMissingModules bundleOption to LocatorResourcePool", a

t.is(builder.createBundle.callCount, 1, "builder.createBundle should be called once");
t.is(builder.createBundle.getCall(0).args.length, 2);
t.deepEqual(builder.createBundle.getCall(0).args[0], effectiveBundleDefinition,
t.deepEqual(builder.createBundle.getCall(0).args[0], bundleDefinition,
"builder.createBundle should be called with bundleDefinition");
t.deepEqual(builder.createBundle.getCall(0).args[1], effectiveBundleOptions,
"builder.createBundle should be called with bundleOptions");
Expand Down Expand Up @@ -602,17 +539,6 @@ test.serial("Verbose Logging", async (t) => {
"some": "option",
};

const effectiveBundleDefinition = {
// Defaults
"resolve": false,
"resolveConditional": false,
"renderer": false,
"sort": true,
"declareRawModules": false,

"some": "definition"
};

const createdBundle = {
name: "Bundle Name",
content: "Bundle Content",
Expand Down Expand Up @@ -645,6 +571,6 @@ test.serial("Verbose Logging", async (t) => {

t.deepEqual(log.verbose.getCall(0).args, ["Generating bundle:"]);
t.deepEqual(log.verbose.getCall(1).args,
["bundleDefinition: " + JSON.stringify(effectiveBundleDefinition, null, 2)]);
["bundleDefinition: " + JSON.stringify(bundleDefinition, null, 2)]);
t.deepEqual(log.verbose.getCall(2).args, ["bundleOptions: " + JSON.stringify(effectiveBundleOptions, null, 2)]);
});
Loading

0 comments on commit dfa67fe

Please sign in to comment.