Description
Preconditions
- Magento 2.1.12
Steps to reproduce
- Inject a script very early in the page, that requires section-config.js and trigger its method getAffectedSections("some page").
Example reproduction code
(Or just use this example module - https://github.com/kshaa/m2-section-config-oddity/)
vendor/magento/module-theme/view/base/templates/root.phtml
(Root.phtml is not the proper place for customization, this is just an example for the issue)
<?php
/**
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
// @codingStandardsIgnoreFile
?>
<!doctype html>
<html <?php /* @escapeNotVerified */ echo $htmlAttributes ?>>
<head <?php /* @escapeNotVerified */ echo $headAttributes ?>>
<?php /* @escapeNotVerified */ echo $requireJs ?>
<?php /* @escapeNotVerified */ echo $headContent ?>
<?php /* @escapeNotVerified */ echo $headAdditional ?>
</head>
<body data-container="body" data-mage-init='{"loaderAjax": {}, "loader": { "icon": "<?php /* @escapeNotVerified */ echo $loaderIcon; ?>"}}' <?php /* @escapeNotVerified */ echo $bodyAttributes ?>>
<script>
require([
"Vendor_Theme/js/test"
], function(test) {
var affectedSections = test("some page");
});
</script>
<?php /* @escapeNotVerified */ echo $layoutContent ?>
</body>
</html>
app/code/Vendor/Theme/view/frontend/web/js/test.js
define([
'jquery', // Because everything requires jQuery
'Magento_Customer/js/section-config'
], function($, sectionConfig) {
return function(page) {
sectionConfig.getAffectedSections(page);
}
});
Expected result
- RequireJS will load section-config.js
- section-config.js constructs and initiates itself as required
- My injected script receives all affected sections for the URL "some page"
Actual result
- RequireJS loads section-config.js, but the internal data section-config requires for functioning isn't loaded yet
- section-config.js throws an error: "Uncaught TypeError: Cannot read property '*' of undefined"
Extra information
How I expect this internal section-config data load works usually
I think the data for section-config usually gets initiated in the following way:
vendor/magento/module-customer/view/frontend/templates/js/section-config.phtml template embeds the section-config with an x-magento-init script and also provides the required internal data
lib/web/mage/apply/scripts.js triggers early on page-load and transforms that x-magento-init into a virtual component (JS variable to-be-processed)
lib/web/mage/apply/main.js loads that section-config virtual component and binds the data from the template by passing it to a function that corresponds to the section-config returned object key "Magento_Customer/js/section-config".
Questions and concerns
- That "usual" data loading approach only works if section-config gets first loaded by the x-magento-init mechanism, however it's not given that will always be the case.
- Is it documented somewhere that I'm not allowed to use a bare-bones 'require' function for receiving section-config and other base features?
- I didn't manage to reproduce the following idea, but - if I x-magento-init'ed that test.js and once again required section-config, then it should also fail right? Because main.js (the x-magento-init JS mechanism) wouldn't have loaded the internal section-config data, because it simply uses a bare-bones require without any safety-checks.
Am I missing something critical here? Does the x-magento-init mechanism have drawbacks/limitations that I haven't seen in the documentations?
I just want to understand how this works, maybe this is actually easy and I didn't notice something.
P.S. I found this issue, because somewhere early in my page is a bare-bones JS using require that calls section-config within it's long dependency tree and fails in the aforementioned way and I can't easily fix it by replacing that initial script with x-magento-init or by moving it lower in the page, because I don't know what initial script triggers this faulty dependency tree.
P.P.S. This also seems like a race-condition which depends on the time it takes to load JS libraries over the network. Sometimes there is an error, sometimes not, but that shouldn't happen.