-
Notifications
You must be signed in to change notification settings - Fork 23
[FIX] generateResourcesJson: Make resources.json generation deterministic #551
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
9093861
to
245b592
Compare
Obviously still missing dedicated tests for the added code and parameters. We could not measure any immediate performance improvement. We also discussed alternative implementations. Including one even more similar to how Maven does it, where we generate the resources.json information during the bundling (where no debug files exist yet) and enrich it with the debug file information at a later point. Either while they are being created or in a separate task. But this would be a bigger effort than what this PR does. |
lib/lbt/resources/ResourcePool.js
Outdated
let info = this._dependencyInfos.get(name); | ||
if ( info == null ) { | ||
// console.log("analyzing ", name); | ||
let dbgResource; | ||
if (options && options.preferDebugResources) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels somehow wrong. Complicating the ResourcePool for a late task by adding difficult to understand logic that's not needed in earlier tasks.
Maybe thinking of tasks in a more holistic way would be better. Currently, we see tasks as modifying or creating files, but maybe they rather should be transformations of the project (or the projects build results) into another, consistent build result.
With that interpretation, an early task would determine dependencies on the original sources and store them in an early version of the resources.json.
createDebugFiles, when executed, would have to update that file. The logic which files will be copied and which not, would then be isolated in the createDebugFiles task (or processor, I don't know) and not being spread across tasks.
All bundling task obviously also would have to update any existing resources.json.
Well, but even with that approach, encapsulation would not be a no-brainer. All the mentioned tasks would have to know where a resources.json files can exist (library, component, theme).
lib/lbt/resources/ResourcePool.js
Outdated
// not-minified content of a resource. | ||
const dbgName = ResourceInfoList.getDebugName(name); | ||
if (dbgName && (!options.debugBundleFilter || !options.debugBundleFilter.matches(dbgName))) { | ||
dbgResource = this._resourcesByName.get(dbgName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Making findResource
async was meant as a preparation to later switch from a prepare and wrap approach to a direct access via the fs adapters. But I guess you wanted to avoid the (ugly) try catch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe that's the best approach then? Rewriting the ResourcePool to tightly integrate with ui5-fs. Also, adding a new Class in ui5-fs to store metadata like the AST (or plain dependency information?) per-resource.
Every task modifying a resource should update this metadata or at least invalidate it in some way.
Then there would still be a final resource.json-generation task, but instead of analyzing resources it would use the metadata already available for most of them.
promises.push( | ||
this.enrichWithDependencyInfo(info) | ||
); | ||
if ( (!info.isDebug || debugBundleFilter.matches(name)) ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this strange now to focus on non-debug resources here, but then in the ResourcePool doing the opposite and prefer the debug resource?
My statement that we should run over the non-debug sources was motivated by the fact that not every resources has a related dbg-resource.
But couldn't we check that here in the ResourceCollector and keep the logic out of the pool?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed, the mentioned change in ResourcePool has been retracted from this PR. Just to have it documented somewhere I created #553
245b592
to
374e0c0
Compare
…stic Stop analyzing debug-resources if they correspond to a non-debug resource. Only analyze the non-debug resource and copy any dependency information to the corresponding debug-resource. While this might not be the best approach given that analyzing the source ("debug") version of a resource might result in finding more dependencies (i.e. those mangled during minification), this change ensures that we generate the same resources.json, independently from the order of debug and non-debug resources supplied to the resourceListCreator processor. Resolves SAP/ui5-tooling#274
a279872
to
7ec38a4
Compare
…e content Possible follow up of #551 to improve dependency analysis. JSModuleAnalyzer has trouble detecting some dependencies in minified code if they have been "mangled". E.g. in case jQuery is not named jQuery anymore. This change solves that by trying to retrieve the debug ("source") content of a resource to analyze that instead of the minified version. However, integrating this on the ResourcePool level is not ideal and a more general solution to this problem should be preferred. Therefore this PR should only act as an illustration of the discussions and thoughts. Currently it should not be merged.
…e content Possible follow up of #551 to improve dependency analysis. JSModuleAnalyzer has trouble detecting some dependencies in minified code if they have been "mangled". E.g. in case jQuery is not named jQuery anymore. This change solves that by trying to retrieve the debug ("source") content of a resource to analyze that instead of the minified version. However, integrating this on the ResourcePool level is not ideal and a more general solution to this problem should be preferred. Therefore this PR should only act as an illustration of the discussions and thoughts. Currently it should not be merged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
this.enrichWithDependencyInfo(info) | ||
); | ||
if ( (!info.isDebug || debugBundleFilter.matches(name)) ) { | ||
// Only analyze non-debug files which are not special debug bundles (like sap-ui-core-dbg.js) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Only analyze non-debug files which are not special debug bundles (like sap-ui-core-dbg.js) | |
// Only analyze non-debug files and special debug bundles (like sap-ui-core-dbg.js) |
or am I wrong?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Absolutely right 👍
@@ -253,19 +272,17 @@ class ResourceCollector { | |||
|
|||
groupResourcesByComponents(options) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
options
could be removed completely, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes 🙌
const enrichWithDependencyInfoStub = sinon.stub(resourceCollector, "enrichWithDependencyInfo") | ||
.callsFake((resourceInfo) => { | ||
// Simulate enriching resource info with dependency info to test whether it gets shared | ||
// with the dbg resource alter on |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// with the dbg resource alter on | |
// with the dbg resource later on |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
newDbgInfo.copyFrom(null, nonDbgInfo); | ||
newDbgInfo.copyFrom(null, dbgInfo); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
newDbgInfo.copyFrom(null, nonDbgInfo); | |
newDbgInfo.copyFrom(null, dbgInfo); | |
newDbgInfo.copyFrom(null, nonDbgInfo); // First copy info of analysis from non-dbg file (included, required, condRequired, ...) | |
newDbgInfo.copyFrom(null, dbgInfo); // Then copy over info from dbg file to properly set name, isDebug, ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Stop analyzing debug-resources if they correspond to a non-debug resource.
Only analyze the non-debug resource and copy any dependency information to the corresponding debug-resource.
While this might not be the best approach given that analyzing the source ("debug") version of a resource might result in finding more dependencies (i.e. those mangled during minification), this change ensures that we generate the same resources.json, independently from the order of debug and non-debug resources supplied to the resourceListCreator processor.
Resolves SAP/ui5-tooling#274