builder/lib/tasks/bundlers/generateBundle.js

  1. import moduleBundler from "../../processors/bundlers/moduleBundler.js";
  2. import {applyDefaultsToBundleDefinition} from "./utils/applyDefaultsToBundleDefinition.js";
  3. import createModuleNameMapping from "./utils/createModuleNameMapping.js";
  4. import ReaderCollectionPrioritized from "@ui5/fs/ReaderCollectionPrioritized";
  5. /**
  6. * @public
  7. * @module @ui5/builder/tasks/bundlers/generateBundle
  8. */
  9. /* eslint-disable max-len */
  10. /**
  11. * Generates a bundle based on the given bundle definition
  12. *
  13. * @public
  14. * @function default
  15. * @static
  16. *
  17. * @param {object} parameters Parameters
  18. * @param {@ui5/fs/DuplexCollection} parameters.workspace DuplexCollection to read and write files
  19. * @param {@ui5/fs/ReaderCollection} parameters.dependencies Collection to read dependency files
  20. * @param {@ui5/project/build/helpers/TaskUtil|object} [parameters.taskUtil] TaskUtil
  21. * @param {object} parameters.options Options
  22. * @param {string} parameters.options.projectName Project name
  23. * @param {module:@ui5/builder/processors/bundlers/moduleBundler~ModuleBundleDefinition} parameters.options.bundleDefinition Module
  24. * bundle definition
  25. * @param {module:@ui5/builder/processors/bundlers/moduleBundler~ModuleBundleOptions} [parameters.options.bundleOptions] Module
  26. * bundle options
  27. * @returns {Promise} Promise resolving with <code>undefined</code> once data has been written
  28. */
  29. /* eslint-enable max-len */
  30. export default async function({
  31. workspace, dependencies, taskUtil, options: {projectName, bundleDefinition, bundleOptions}
  32. }) {
  33. let combo = new ReaderCollectionPrioritized({
  34. name: `generateBundle - prioritize workspace over dependencies: ${projectName}`,
  35. readers: [workspace, dependencies]
  36. });
  37. const optimize = !bundleOptions || bundleOptions.optimize !== false;
  38. if (taskUtil) {
  39. /* Scenarios
  40. 1. Optimize bundle with minification already done
  41. Workspace:
  42. * /resources/my/lib/Control.js [ui5:HasDebugVariant]
  43. * /resources/my/lib/Control.js.map [ui5:HasDebugVariant]
  44. * /resources/my/lib/Control-dbg.js [ui5:IsDebugVariant]
  45. Bundler input:
  46. * /resources/my/lib/Control.js
  47. * /resources/my/lib/Control.js.map
  48. => Filter out debug resources
  49. 2. Optimize bundle with no minification
  50. * /resources/my/lib/Control.js
  51. => No action necessary
  52. 3. Debug-bundle with minification already done
  53. Workspace:
  54. * /resources/my/lib/Control.js [ui5:HasDebugVariant]
  55. * /resources/my/lib/Control.js.map [ui5:HasDebugVariant]
  56. * /resources/my/lib/Control-dbg.js [ui5:IsDebugVariant]
  57. Bundler input:
  58. * /resources/my/lib/Control-dbg.js
  59. * moduleNameMapping: [{"/resources/my/lib/Control-dbg.js": "my/lib/Control.js"}]
  60. => Filter out minified-resources (tagged as "HasDebugVariant", incl. source maps) and rename debug-files
  61. 4. Debug-bundle with no minification
  62. * /resources/my/lib/Control.js
  63. => No action necessary
  64. 5. Bundle with external input (optimize or not), e.g. TS-project
  65. Workspace:
  66. * /resources/my/lib/Control.ts
  67. * /resources/my/lib/Control.js
  68. * /resources/my/lib/Control.js.map
  69. Bundler input:
  70. * /resources/my/lib/Control.js
  71. * /resources/my/lib/Control.js.map
  72. */
  73. // Omit -dbg files for optimize bundles and vice versa
  74. const filterTag = optimize ?
  75. taskUtil.STANDARD_TAGS.IsDebugVariant : taskUtil.STANDARD_TAGS.HasDebugVariant;
  76. combo = taskUtil.resourceFactory.createFilterReader({
  77. reader: combo,
  78. callback: function(resource) {
  79. return !taskUtil.getTag(resource, filterTag);
  80. }
  81. });
  82. }
  83. const coreVersion = taskUtil?.getProject("sap.ui.core")?.getVersion();
  84. const allowStringBundling = taskUtil?.getProject().getSpecVersion().lt("4.0");
  85. return combo.byGlob("/resources/**/*.{js,json,xml,html,properties,library,js.map}").then((resources) => {
  86. const options = {
  87. bundleDefinition: applyDefaultsToBundleDefinition(bundleDefinition, taskUtil),
  88. bundleOptions,
  89. allowStringBundling
  90. };
  91. if (!optimize && taskUtil) {
  92. options.moduleNameMapping = createModuleNameMapping({resources, taskUtil});
  93. }
  94. if (coreVersion) {
  95. options.targetUi5CoreVersion = coreVersion;
  96. }
  97. return moduleBundler({options, resources}).then((bundles) => {
  98. return Promise.all(bundles.map(({bundle, sourceMap} = {}) => {
  99. if (!bundle) {
  100. // Skip empty bundles
  101. return;
  102. }
  103. if (taskUtil) {
  104. taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
  105. if (sourceMap) {
  106. // Clear tag that might have been set by the minify task, in cases where
  107. // the bundle name is identical to a source file
  108. taskUtil.clearTag(sourceMap, taskUtil.STANDARD_TAGS.OmitFromBuildResult);
  109. }
  110. }
  111. const writes = [workspace.write(bundle)];
  112. if (sourceMap) {
  113. writes.push(workspace.write(sourceMap));
  114. }
  115. return Promise.all(writes);
  116. }));
  117. });
  118. });
  119. }