Skip to content

Commit d6aaeb9

Browse files
committed
Build DepCache info files (*-h2-preload.js) for better HTTP/2 support
1 parent 33c8190 commit d6aaeb9

File tree

5 files changed

+177
-50
lines changed

5 files changed

+177
-50
lines changed

lib/lbt/analyzer/JSModuleAnalyzer.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@ const CALL_JQUERY_SAP_IS_DECLARED = [["jQuery", "$"], "sap", "isDeclared"];
151151
const CALL_JQUERY_SAP_REQUIRE = [["jQuery", "$"], "sap", "require"];
152152
const CALL_JQUERY_SAP_REGISTER_PRELOADED_MODULES = [["jQuery", "$"], "sap", "registerPreloadedModules"];
153153

154+
const SPECIAL_AMD_DEPENDENCIES = ["require", "exports", "module"];
155+
154156

155157
/**
156158
* Analyzes an already parsed JSDocument to collect information about the contained module(s).
@@ -470,6 +472,10 @@ class JSModuleAnalyzer {
470472
// console.log(array);
471473
array.forEach( (item) => {
472474
if ( isString(item) ) {
475+
// ignore special AMD dependencies (require, exports, module)
476+
if ( SPECIAL_AMD_DEPENDENCIES.indexOf(item.value) >= 0 ) {
477+
return;
478+
}
473479
let requiredModule;
474480
if (name == null) {
475481
requiredModule = ModuleName.fromRequireJSName( item.value );

lib/lbt/bundle/Builder.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ const UI5BundleFormat = {
5050
outW.writeln(`}});`);
5151
},
5252

53+
beforeH2Preloads(outW) {
54+
outW.writeln(`"unsupported"; /* Bundle format 'h2' not supported (requires ui5loader)`);
55+
},
56+
57+
afterH2Preloads(outW) {
58+
outW.writeln(`*/`);
59+
},
60+
5361
requireSync(outW, moduleName) {
5462
outW.writeln(`sap.ui.requireSync("${ModuleName.toRequireJSName(moduleName)}");`);
5563
},
@@ -76,6 +84,14 @@ const EVOBundleFormat = {
7684
outW.writeln(`);`);
7785
},
7886

87+
beforeH2Preloads(outW) {
88+
outW.writeln(`sap.ui.loader.config({depCacheUI5:{`);
89+
},
90+
91+
afterH2Preloads(outW) {
92+
outW.writeln(`}});`);
93+
},
94+
7995
requireSync(outW, moduleName) {
8096
outW.writeln(`sap.ui.requireSync("${ModuleName.toRequireJSName(moduleName)}");`);
8197
},
@@ -204,6 +220,8 @@ class BundleBuilder {
204220
return this.writeRaw(section);
205221
case SectionType.Preload:
206222
return this.writePreloadFunction(section);
223+
case SectionType.DepCache:
224+
return this.writeDepCache(section);
207225
case SectionType.Require:
208226
return this.writeRequires(section);
209227
default:
@@ -480,6 +498,43 @@ class BundleBuilder {
480498
});
481499
}
482500

501+
async writeDepCache(section) {
502+
const outW = this.outW;
503+
504+
outW.ensureNewLine();
505+
506+
const sequence = section.modules.slice();
507+
508+
if ( sequence.length > 0 ) {
509+
this.targetBundleFormat.beforeH2Preloads(outW, section);
510+
let i = 0;
511+
for (let module of sequence) {
512+
let resource = await this.pool.findResourceWithInfo(module);
513+
if ( resource != null ) {
514+
let deps = resource.info.dependencies.filter(dep =>
515+
!resource.info.isConditionalDependency(dep) && !resource.info.isImplicitDependency(dep) );
516+
if ( deps.length > 0 ) {
517+
if ( i > 0 ) {
518+
outW.writeln(",");
519+
}
520+
outW.write(`"${module}": [${deps.map(dep=>"\"" + dep + "\"").join(",")}]`);
521+
i++;
522+
} else {
523+
log.verbose(" skipped %s, no dependencies", module);
524+
}
525+
} else {
526+
log.error(" couldn't find %s", module);
527+
}
528+
}
529+
530+
if ( i > 0 ) {
531+
outW.writeln();
532+
}
533+
this.targetBundleFormat.afterH2Preloads(outW, section);
534+
}
535+
536+
}
537+
483538
writeRequires(section) {
484539
this.outW.ensureNewLine();
485540
section.modules.forEach( (module) => {

lib/lbt/bundle/BundleDefinition.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ const SectionType = {
1717
*/
1818
Preload: "preload",
1919

20+
/**
21+
* Only the dependencies of the modules are stored as 'depCache' configuration.
22+
* Requires UI5 Evolution runtime.
23+
*/
24+
DepCache: "depcache",
25+
2026
/**
2127
* For each module, a jQuery.sap.require call will be created.
2228
* Usually used as the last section in a merged module to enforce loading and

lib/tasks/bundlers/generateComponentPreload.js

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -56,24 +56,54 @@ module.exports = function({workspace, dependencies, options}) {
5656
}
5757
});
5858

59-
return moduleBundler({
60-
resources,
61-
options: {
62-
bundleDefinition: {
63-
name: `${namespace}/Component-preload.js`,
64-
defaultFileTypes: [".js", ".fragment.xml", ".view.xml", ".properties", ".json"],
65-
sections: [
66-
{
67-
mode: "preload",
68-
filters: filters,
69-
resolve: false,
70-
resolveConditional: false,
71-
renderer: false
72-
}
73-
]
59+
return Promise.all([
60+
moduleBundler({
61+
resources,
62+
options: {
63+
bundleDefinition: {
64+
name: `${namespace}/Component-preload.js`,
65+
defaultFileTypes: [".js", ".fragment.xml", ".view.xml", ".properties", ".json"],
66+
sections: [
67+
{
68+
mode: "preload",
69+
filters: filters,
70+
resolve: false,
71+
resolveConditional: false,
72+
renderer: false
73+
}
74+
]
75+
}
7476
}
75-
}
76-
});
77+
}),
78+
moduleBundler({
79+
resources,
80+
options: {
81+
bundleDefinition: {
82+
name: `${namespace}/Component-h2-preload.js`,
83+
defaultFileTypes: [".js", ".fragment.xml", ".view.xml", ".properties", ".json"],
84+
sections: [
85+
{
86+
mode: "preload",
87+
filters: [
88+
`${namespace}/library.js`,
89+
`${namespace}/manifest.json`
90+
],
91+
resolve: false,
92+
resolveConditional: false,
93+
renderer: false
94+
},
95+
{
96+
mode: "depcache",
97+
filters: filters,
98+
resolve: false,
99+
resolveConditional: false,
100+
renderer: false
101+
}
102+
]
103+
}
104+
}
105+
})
106+
]);
77107
}));
78108
})
79109
.then((processedResources) => {

lib/tasks/bundlers/generateLibraryPreload.js

Lines changed: 63 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@ const log = require("@ui5/logger").getLogger("builder:tasks:bundlers:generateLib
22
const moduleBundler = require("../../processors/bundlers/moduleBundler");
33
const ReaderCollectionPrioritized = require("@ui5/fs").ReaderCollectionPrioritized;
44

5-
function getBundleDefinition(namespace) {
5+
function getBundleDefinition(namespace, h2) {
6+
let h2infix = h2 ? "h2-" : "";
7+
let bundleDef;
68
// TODO: move to config of actual core project
79
if (namespace === "sap/ui/core") {
8-
return {
9-
name: `${namespace}/library-preload.js`,
10+
bundleDef = {
11+
name: `${namespace}/library-${h2infix}preload.js`,
1012
defaultFileTypes: [".js", ".fragment.xml", ".view.xml", ".properties", ".json"],
1113
sections: [
1214
{
13-
mode: "preload",
15+
mode: h2 ? "depcache" : "preload",
1416
filters: [
1517
`${namespace}/`,
1618
`!${namespace}/.library`,
@@ -41,27 +43,42 @@ function getBundleDefinition(namespace) {
4143
}
4244
]
4345
};
46+
} else {
47+
bundleDef = {
48+
name: `${namespace}/library-${h2infix}preload.js`,
49+
defaultFileTypes: [".js", ".fragment.xml", ".view.xml", ".properties", ".json"],
50+
sections: [
51+
{
52+
mode: h2 ? "depcache" : "preload",
53+
filters: [
54+
`${namespace}/`,
55+
`!${namespace}/.library`,
56+
`!${namespace}/themes/`,
57+
`!${namespace}/messagebundle*`
58+
],
59+
resolve: false,
60+
resolveConditional: false,
61+
renderer: true
62+
}
63+
]
64+
};
4465
}
45-
return {
46-
name: `${namespace}/library-preload.js`,
47-
defaultFileTypes: [".js", ".fragment.xml", ".view.xml", ".properties", ".json"],
48-
sections: [
49-
{
50-
mode: "preload",
51-
filters: [
52-
`${namespace}/`,
53-
`!${namespace}/.library`,
54-
`!${namespace}/themes/`,
55-
`!${namespace}/messagebundle*`
56-
],
57-
resolve: false,
58-
resolveConditional: false,
59-
renderer: true
60-
}
61-
]
62-
};
66+
if ( h2 ) {
67+
bundleDef.sections.unshift({
68+
mode: "preload",
69+
filters: [
70+
`${namespace}/library.js`,
71+
`${namespace}/manifest.json`
72+
],
73+
resolve: false,
74+
resolveConditional: false,
75+
renderer: false
76+
});
77+
}
78+
return bundleDef;
6379
}
6480

81+
6582
/**
6683
* Task for library bundling.
6784
*
@@ -168,17 +185,30 @@ module.exports = function({workspace, dependencies, options}) {
168185
const libraryNamespaceMatch = libraryIndicatorPath.match(libraryNamespacePattern);
169186
if (libraryNamespaceMatch && libraryNamespaceMatch[1]) {
170187
const libraryNamespace = libraryNamespaceMatch[1];
171-
return moduleBundler({
172-
options: {
173-
bundleDefinition: getBundleDefinition(libraryNamespace)
174-
},
175-
resources
176-
}).then(([bundle]) => {
177-
if (bundle) {
178-
// console.log(`${libraryNamespace}/library-preload.js bundle created`);
179-
return workspace.write(bundle);
180-
}
181-
});
188+
return Promise.all([
189+
moduleBundler({
190+
options: {
191+
bundleDefinition: getBundleDefinition(libraryNamespace)
192+
},
193+
resources
194+
}).then(([bundle]) => {
195+
if (bundle) {
196+
// console.log(`${libraryNamespace}/library-preload.js bundle created`);
197+
return workspace.write(bundle);
198+
}
199+
}),
200+
moduleBundler({
201+
options: {
202+
bundleDefinition: getBundleDefinition(libraryNamespace, /* h2 */ true)
203+
},
204+
resources
205+
}).then(([bundle]) => {
206+
if (bundle) {
207+
// console.log(`${libraryNamespace}/library-h2-preload.js bundle created`);
208+
return workspace.write(bundle);
209+
}
210+
})
211+
]);
182212
} else {
183213
log.verbose(`Could not determine library namespace from file "${libraryIndicatorPath}" for project ${options.projectName}. Skipping library preload bundling.`);
184214
return Promise.resolve();

0 commit comments

Comments
 (0)