admin管理员组文章数量:1023856
I'm migrating JS scripts to ES6 modules. A mon pattern of client-side code is to push tracking information to global arrays on the window
object. One concrete example of that is GTM window.dataLayer
array.
I'd like to abstract these globals into ES6 modules, instead of instructing the linter to ignore them with /* global dataLayer */
, as it makes the code easier to understand. My first try was to create shims like these:
export default window.dataLayer;
However, as explained here in the "Implementing Views" section, the above code is equivalent to:
const *default* = window.dataLayer; // *not* legal JavaScript
export { *default* as default };
As such, the window.dataLayer
array within each module would be a copy of the original window.dataLater
array: when GTM bootstraps, asynchronously, the events pushed from the modules won't be seen by it as only the local *default*
would have those events.
What is the remended way to deal with globals like these with ES6 modules, which does not involve heavy-weight solution like using a Proxy? It does feel bad having lots of globals around in a modular system.
I'm migrating JS scripts to ES6 modules. A mon pattern of client-side code is to push tracking information to global arrays on the window
object. One concrete example of that is GTM window.dataLayer
array.
I'd like to abstract these globals into ES6 modules, instead of instructing the linter to ignore them with /* global dataLayer */
, as it makes the code easier to understand. My first try was to create shims like these:
export default window.dataLayer;
However, as explained here in the "Implementing Views" section, the above code is equivalent to:
const *default* = window.dataLayer; // *not* legal JavaScript
export { *default* as default };
As such, the window.dataLayer
array within each module would be a copy of the original window.dataLater
array: when GTM bootstraps, asynchronously, the events pushed from the modules won't be seen by it as only the local *default*
would have those events.
What is the remended way to deal with globals like these with ES6 modules, which does not involve heavy-weight solution like using a Proxy? It does feel bad having lots of globals around in a modular system.
Share Improve this question asked Jan 18, 2016 at 19:15 laurentgoudetlaurentgoudet 311 silver badge4 bronze badges 2- 2 Nothing in your example makes a copy of the array, so I'm not sure what you're really asking. – loganfsmyth Commented Jan 18, 2016 at 19:48
-
2
The sentence "As such, the
window.dataLayer
array within each module would be a copy of the originalwindow.dataLater
array" doesn't make any sense. – Bergi Commented Jan 18, 2016 at 22:24
1 Answer
Reset to default 5Contrary to what you describe in the question, the proper way to deal with this would be:
/* data-layer.js */
window.dataLayer = [];
export default window.dataLayer;
...and any modules that needed to push on to the "dataLayer" array, would just need something like:
import dataLayer from 'data-layer';
// ... some code I assume
dataLayer.push({
'pageCategory': 'signup',
'visitorType': 'high-value'
});
Because ES6 imports pass a read-only reference to the export, so it's not a copy of the array you are importing, it is the array created and exported in data-layer.js.
But the tricky part there then is then you'll have to modify the Google Tag Manager container snippet to not run as soon as it is loaded, but rather to only run after all the scripts that may modify dataLayer
have run.
If you are loading the GTM Container Snippet as a module on it's own, you may want to import all the scripts that may modify the dataLater first (and make sure that part actually runs) before you invoke the snippet.
Something like:
/* gtm-container.js */
import 'this';
import 'that';
import otherThing from 'the-other-thing'; // lets assume it returns a promise
import dataLayer from 'data-layer'l
otherThing.then(value => {
invokeSnippet()
})
.catch(err => {
handleError(err);
});
function invokeSnippet() {
(function(w,d,s,i){dataLayer.push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'//www.googletagmanager./gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXX')
}
But, you know that's not really an explanation of how to do that, just an idea, I have no idea what different things may add to the dataLayer and because you are moving to an asynchronous module pattern, you are going to have to understand how running all these scripts asynchronously are going to change how you use the GTM system, which was clearly written to run synchronously using globals.
I wonder if Google will update these things with modern JavaScript soon, or if there is a more modular option available.
I should mention in case you don't know:
Many (most) ES6/ES2015 features, including modules, are not available in browsers as of today (Jan 2016), so you'll need some sort of build or loader in place to make these things work in the browser (Like webpack, browserify, stealjs, jspm, or something with babel or tracuer or something)
http://stealjs./ is probably the easiest to get started with.
I'm migrating JS scripts to ES6 modules. A mon pattern of client-side code is to push tracking information to global arrays on the window
object. One concrete example of that is GTM window.dataLayer
array.
I'd like to abstract these globals into ES6 modules, instead of instructing the linter to ignore them with /* global dataLayer */
, as it makes the code easier to understand. My first try was to create shims like these:
export default window.dataLayer;
However, as explained here in the "Implementing Views" section, the above code is equivalent to:
const *default* = window.dataLayer; // *not* legal JavaScript
export { *default* as default };
As such, the window.dataLayer
array within each module would be a copy of the original window.dataLater
array: when GTM bootstraps, asynchronously, the events pushed from the modules won't be seen by it as only the local *default*
would have those events.
What is the remended way to deal with globals like these with ES6 modules, which does not involve heavy-weight solution like using a Proxy? It does feel bad having lots of globals around in a modular system.
I'm migrating JS scripts to ES6 modules. A mon pattern of client-side code is to push tracking information to global arrays on the window
object. One concrete example of that is GTM window.dataLayer
array.
I'd like to abstract these globals into ES6 modules, instead of instructing the linter to ignore them with /* global dataLayer */
, as it makes the code easier to understand. My first try was to create shims like these:
export default window.dataLayer;
However, as explained here in the "Implementing Views" section, the above code is equivalent to:
const *default* = window.dataLayer; // *not* legal JavaScript
export { *default* as default };
As such, the window.dataLayer
array within each module would be a copy of the original window.dataLater
array: when GTM bootstraps, asynchronously, the events pushed from the modules won't be seen by it as only the local *default*
would have those events.
What is the remended way to deal with globals like these with ES6 modules, which does not involve heavy-weight solution like using a Proxy? It does feel bad having lots of globals around in a modular system.
Share Improve this question asked Jan 18, 2016 at 19:15 laurentgoudetlaurentgoudet 311 silver badge4 bronze badges 2- 2 Nothing in your example makes a copy of the array, so I'm not sure what you're really asking. – loganfsmyth Commented Jan 18, 2016 at 19:48
-
2
The sentence "As such, the
window.dataLayer
array within each module would be a copy of the originalwindow.dataLater
array" doesn't make any sense. – Bergi Commented Jan 18, 2016 at 22:24
1 Answer
Reset to default 5Contrary to what you describe in the question, the proper way to deal with this would be:
/* data-layer.js */
window.dataLayer = [];
export default window.dataLayer;
...and any modules that needed to push on to the "dataLayer" array, would just need something like:
import dataLayer from 'data-layer';
// ... some code I assume
dataLayer.push({
'pageCategory': 'signup',
'visitorType': 'high-value'
});
Because ES6 imports pass a read-only reference to the export, so it's not a copy of the array you are importing, it is the array created and exported in data-layer.js.
But the tricky part there then is then you'll have to modify the Google Tag Manager container snippet to not run as soon as it is loaded, but rather to only run after all the scripts that may modify dataLayer
have run.
If you are loading the GTM Container Snippet as a module on it's own, you may want to import all the scripts that may modify the dataLater first (and make sure that part actually runs) before you invoke the snippet.
Something like:
/* gtm-container.js */
import 'this';
import 'that';
import otherThing from 'the-other-thing'; // lets assume it returns a promise
import dataLayer from 'data-layer'l
otherThing.then(value => {
invokeSnippet()
})
.catch(err => {
handleError(err);
});
function invokeSnippet() {
(function(w,d,s,i){dataLayer.push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'//www.googletagmanager./gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXX')
}
But, you know that's not really an explanation of how to do that, just an idea, I have no idea what different things may add to the dataLayer and because you are moving to an asynchronous module pattern, you are going to have to understand how running all these scripts asynchronously are going to change how you use the GTM system, which was clearly written to run synchronously using globals.
I wonder if Google will update these things with modern JavaScript soon, or if there is a more modular option available.
I should mention in case you don't know:
Many (most) ES6/ES2015 features, including modules, are not available in browsers as of today (Jan 2016), so you'll need some sort of build or loader in place to make these things work in the browser (Like webpack, browserify, stealjs, jspm, or something with babel or tracuer or something)
http://stealjs./ is probably the easiest to get started with.
本文标签: javascriptReexport global variables with ES6 modulesStack Overflow
版权声明:本文标题:javascript - Re-export global variables with ES6 modules - Stack Overflow 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1745568287a2156582.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论