Skip to content

Commit 064d225

Browse files
committed
refactor: Compare ui5-tooling-modules npm build with the custom implementation
1 parent 98693ed commit 064d225

9 files changed

Lines changed: 517 additions & 220 deletions

File tree

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/**
2+
* UI5-Tooling-Modules Bundler Wrapper
3+
*
4+
* Wraps ui5-tooling-modules to provide a consistent API for comparison
5+
* with our custom Rollup-based bundler.
6+
*/
7+
8+
import {createRequire} from "module";
9+
import {mkdir, writeFile, readFile} from "fs/promises";
10+
import {join, dirname} from "path";
11+
import {fileURLToPath} from "url";
12+
13+
const __dirname = dirname(fileURLToPath(import.meta.url));
14+
const require = createRequire(import.meta.url);
15+
16+
// Read the package.json for proper projectInfo
17+
const pkgJsonPath = join(__dirname, "../package.json");
18+
let pkgJson;
19+
try {
20+
pkgJson = JSON.parse(await readFile(pkgJsonPath, "utf-8"));
21+
} catch {
22+
pkgJson = {
23+
name: "npm-integration-poc",
24+
version: "1.0.0"
25+
};
26+
}
27+
28+
// Create a proper projectInfo for the util module
29+
const projectInfo = {
30+
name: "npm-integration-poc",
31+
namespace: "npm/integration/poc",
32+
type: "application",
33+
framework: {
34+
name: "SAPUI5",
35+
version: "1.120.0" // Minimum version for WebComponents support
36+
},
37+
pkgJson // ui5-tooling-modules needs this!
38+
};
39+
40+
// Minimal logger
41+
const log = {
42+
verbose: () => {},
43+
info: (msg) => console.log(` [ui5-tooling-modules] ${msg}`),
44+
warn: (msg) => console.warn(` [ui5-tooling-modules] ⚠️ ${msg}`),
45+
error: (msg) => console.error(` [ui5-tooling-modules] ❌ ${msg}`)
46+
};
47+
48+
/**
49+
* Bundle a module using ui5-tooling-modules
50+
*
51+
* @param {string|string[]} moduleNames - Module(s) to bundle
52+
* @param {object} options - Configuration options
53+
* @returns {Promise<object>} Bundle info with code and metadata
54+
*/
55+
export async function bundleWithUI5ToolingModules(moduleNames, options = {}) {
56+
// Load the util module (CommonJS)
57+
const utilFactory = require("ui5-tooling-modules/lib/util.js");
58+
const util = utilFactory(log, projectInfo);
59+
60+
// Ensure moduleNames is an array
61+
const modules = Array.isArray(moduleNames) ? moduleNames : [moduleNames];
62+
63+
try {
64+
// Use getBundleInfo which handles caching and returns structured output
65+
const bundleInfo = await util.getBundleInfo(modules, {
66+
skipCache: true,
67+
pluginOptions: options.pluginOptions || {},
68+
...options
69+
}, {
70+
cwd: options.cwd || process.cwd()
71+
});
72+
73+
if (bundleInfo.error) {
74+
throw new Error(`Bundling failed: ${bundleInfo.error.message || bundleInfo.error}`);
75+
}
76+
77+
return bundleInfo;
78+
} catch (error) {
79+
console.error(` [ui5-tooling-modules] Error bundling ${modules.join(", ")}:`, error.message);
80+
throw error;
81+
}
82+
}
83+
84+
/**
85+
* Write ui5-tooling-modules bundle output to dist folder
86+
*
87+
* @param {string} scenarioName - Scenario folder name
88+
* @param {object} bundleInfo - Bundle info from ui5-tooling-modules
89+
* @returns {Promise<string[]>} Array of written file paths
90+
*/
91+
export async function writeUI5ToolingOutput(scenarioName, bundleInfo) {
92+
const outputDir = join(__dirname, `../dist/${scenarioName}/ui5-tooling-modules`);
93+
const writtenFiles = [];
94+
95+
await mkdir(outputDir, {recursive: true});
96+
97+
// Write all entries (modules and chunks)
98+
for (const entry of bundleInfo.getEntries()) {
99+
if (entry.code) {
100+
const fileName = entry.name.endsWith(".js") ? entry.name : `${entry.name}.js`;
101+
const filePath = join(outputDir, fileName);
102+
103+
await mkdir(dirname(filePath), {recursive: true});
104+
await writeFile(filePath, entry.code, "utf-8");
105+
writtenFiles.push({
106+
path: filePath,
107+
name: entry.name,
108+
size: entry.code.length,
109+
type: entry.type
110+
});
111+
}
112+
}
113+
114+
return writtenFiles;
115+
}
116+
117+
/**
118+
* Get the main bundle code from bundleInfo
119+
*
120+
* @param {object} bundleInfo - Bundle info from ui5-tooling-modules
121+
* @param {string} moduleName - Module name to get code for
122+
* @returns {string} Bundle code
123+
*/
124+
export function getMainBundleCode(bundleInfo, moduleName) {
125+
const entry = bundleInfo.getEntry(moduleName);
126+
return entry?.code || "";
127+
}
128+
129+
/**
130+
* Print ui5-tooling-modules bundle summary
131+
*
132+
* @param {object} bundleInfo - Bundle info from ui5-tooling-modules
133+
* @param {string} label - Label for the summary
134+
*/
135+
export function printUI5ToolingSummary(bundleInfo, label = "ui5-tooling-modules") {
136+
const entries = bundleInfo.getEntries();
137+
const modules = bundleInfo.getModules();
138+
const chunks = bundleInfo.getChunks();
139+
140+
let totalSize = 0;
141+
for (const entry of entries) {
142+
if (entry.code) {
143+
totalSize += entry.code.length;
144+
}
145+
}
146+
147+
console.log(`\n📦 ${label} Output:`);
148+
console.log(` Modules: ${modules.length}`);
149+
console.log(` Chunks: ${chunks.length}`);
150+
console.log(` Total size: ${(totalSize / 1024).toFixed(2)} KB`);
151+
152+
// List files
153+
for (const entry of entries) {
154+
if (entry.code) {
155+
const sizeKB = (entry.code.length / 1024).toFixed(2);
156+
const typeIcon = entry.type === "module" ? "📄" : "📦";
157+
console.log(` ${typeIcon} ${entry.name}.js (${sizeKB} KB)`);
158+
}
159+
}
160+
}

internal/npm-integration-poc/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
"lodash": "^4.17.23",
2323
"nanoid": "^5.1.6",
2424
"rollup": "^4.24.4",
25-
"rollup-plugin-polyfill-node": "^0.13.0",
2625
"sinon": "^21.0.1"
2726
},
2827
"devDependencies": {
@@ -32,6 +31,7 @@
3231
"lodash": "^4.17.21",
3332
"lodash-es": "^4.17.21",
3433
"nanoid": "^5.0.9",
35-
"ui5-tooling-modules": "^3.34.2"
34+
"rollup-plugin-polyfill-node": "^0.13.0",
35+
"ui5-tooling-modules": "^3.34.3"
3636
}
3737
}

internal/npm-integration-poc/scenarios/01-esm-integration.js

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,35 +3,32 @@
33
*
44
* Demonstrates bundling a pure ESM-only package (nanoid v5+) for UI5 consumption
55
* nanoid is a modern ESM-only package that cannot be used directly with require()
6+
*
7+
* Compares: Custom Rollup bundler vs ui5-tooling-modules
68
*/
79

810
import {
911
createRollupConfig,
1012
generateAMDBundle,
11-
writeScenarioOutput,
12-
printBundleInfo,
13-
printScenarioHeader
13+
printScenarioHeader,
14+
runDualBundling
1415
} from "./shared-config.js";
1516

16-
printScenarioHeader(1, "ESM Integration - nanoid (Pure ESM)", "Pure ESM-only package → UI5 AMD module");
17-
18-
async function bundleNanoid() {
19-
console.log("\n📦 Bundling nanoid (Pure ESM-only package)...\n");
20-
21-
try {
22-
const config = createRollupConfig("nanoid");
23-
const code = await generateAMDBundle(config);
24-
25-
printBundleInfo(code, "nanoid");
26-
27-
const outputFile = await writeScenarioOutput("01-esm-integration", "nanoid.js", code);
28-
console.log(`\n💾 Saved to: ${outputFile}`);
29-
30-
return code;
31-
} catch (error) {
32-
console.error("❌ Error:", error.message);
33-
throw error;
34-
}
17+
const SCENARIO_NAME = "01-esm-integration";
18+
const PACKAGE_NAME = "nanoid";
19+
20+
printScenarioHeader(1, "ESM Integration - nanoid (Pure ESM)", "Pure ESM-only package → UI5 AMD module\nCompares: Custom Rollup vs ui5-tooling-modules");
21+
22+
try {
23+
await runDualBundling({
24+
scenarioName: SCENARIO_NAME,
25+
packageNames: PACKAGE_NAME,
26+
customBundler: async (pkg) => {
27+
const config = createRollupConfig(pkg);
28+
return await generateAMDBundle(config);
29+
},
30+
});
31+
} catch (error) {
32+
console.error("❌ Error:", error.message);
33+
throw error;
3534
}
36-
37-
bundleNanoid();

internal/npm-integration-poc/scenarios/02-cjs-integration.js

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,32 @@
33
*
44
* Demonstrates bundling a pure CommonJS-only package (lodash) for UI5 consumption
55
* lodash is a classic CJS package that uses require/module.exports exclusively
6+
*
7+
* Compares: Custom Rollup bundler vs ui5-tooling-modules
68
*/
79

810
import {
911
createRollupConfig,
1012
generateAMDBundle,
11-
writeScenarioOutput,
12-
printScenarioHeader
13+
printScenarioHeader,
14+
runDualBundling
1315
} from "./shared-config.js";
1416

15-
printScenarioHeader(2, "CJS Integration - lodash (Pure CJS)", "Pure CommonJS-only package → UI5 AMD module");
16-
17-
async function bundleLodash() {
18-
console.log("\n📦 Bundling lodash (Pure CommonJS-only package)...\n");
19-
20-
try {
21-
const config = createRollupConfig("lodash");
22-
const code = await generateAMDBundle(config);
23-
24-
console.log("✅ Bundle generated successfully!");
25-
console.log(` Package: lodash`);
26-
console.log(` Size: ${(code.length / 1024).toFixed(2)} KB`);
27-
console.log(` Format: AMD (UI5-compatible)`);
28-
console.log(` CommonJS → ESM → AMD conversion successful`);
29-
console.log(`\n📝 First 200 characters:\n${code.substring(0, 200)}...`);
30-
31-
const outputFile = await writeScenarioOutput("02-cjs-integration", "lodash.js", code);
32-
console.log(`\n💾 Saved to: ${outputFile}`);
33-
34-
return code;
35-
} catch (error) {
36-
console.error("❌ Error:", error.message);
37-
throw error;
38-
}
17+
const SCENARIO_NAME = "02-cjs-integration";
18+
const PACKAGE_NAME = "lodash";
19+
20+
printScenarioHeader(2, "CJS Integration - lodash (Pure CJS)", "Pure CommonJS-only package → UI5 AMD module\nCompares: Custom Rollup vs ui5-tooling-modules");
21+
22+
try {
23+
await runDualBundling({
24+
scenarioName: SCENARIO_NAME,
25+
packageNames: PACKAGE_NAME,
26+
customBundler: async (pkg) => {
27+
const config = createRollupConfig(pkg);
28+
return await generateAMDBundle(config);
29+
}
30+
});
31+
} catch (error) {
32+
console.error("❌ Error:", error.message);
33+
throw error;
3934
}
40-
41-
bundleLodash();

0 commit comments

Comments
 (0)