Problem/Motivation
Recently, I encountered an error that would happen on an inconsistent basis. When loading a node with a scorm field after a complete cache clear, the javascript in my Articulate SCORM package would throw an error complaining about the SCORM API not being available. The SCORM API functions are typically added by the opigno scorm player javascript code.
This seemed to happen only on the first page load after a complete cache clearing ("drush cr"). The specific error message from my Articulate-generated SCORM package in the pop-up was
"An error has occurred:
Error - unable to acquire LMS API, content may not play properly and results may not be recorded. Please contact technical support."
I noticed that the issue would not occur at all if I disabled javascript aggregation on my site. In examining changes related to javascript aggregation in D10, I came across this description:
https://www.drupal.org/node/3301716 β
The relevant portion of this page states: "Instead of a page request creating and writing several files before it can be sent to the browser, now the main page request just generates the URLs, and the actual CSS or JavaScript aggregate is individually created by PHP (and still written to disk assuming it's valid)."
So, what was happening was that the server would return a page with URLs for aggregated javascript files that didn't exist yet. The browser would then request those files and, while the server was busy assembling those files in order to send them back the browser, the browser in the meantime had loaded the contents of the iframe, including the SCORM package's javascript code that checks to see whether certain SCORM API functions are available yet. The SCORM package's javascript would see that those SCORM APIs (to be supplied by the opigno_scorm module's javascript code) were not yet available and throw this error, causing the above message to show in a pop-up and ceasing any attempt to play the SCORM file.
Steps to reproduce
As mentioned, the error would happen inconsistently. To replicate it more consistently, I went into the system module's controller, at core/modules/system/src/Controller/AssetControllerBase.js, and modified the deliver() method to sleep for 5 seconds at the beginning of the method if the $file_name parameter to that method ended with ".js". This didn't make the error happen with 100% consistency, but it did happen much more often for me.
Another thing to note is that this error more readily happens on environments that use a distributed file server for its filesystem. This is because I/O operations typically take longer in this scenario, which affects the time it takes to assemble an aggregate file on the fly.
Proposed resolution
In my situation, I got around this problem by overriding the opigno-scorm--player template to serve the same HTML, but without the iframe tag. Then, I used javascript to wait for the document to completely load before creating the necessary iframe tag. This ensures that the SCORM package's contents (and its javascript) is loaded only after the opigno_scorm module's requisite javascript functions are available. I thought this might make the SCORM content load noticeably slower, but I observed almost no difference in the load time.