使用 ES6 模块重新导出全局变量

Re-export global variables with ES6 modules

本文关键字:新导出 全局变量 模块 ES6 使用      更新时间:2023-09-26

我正在将JS脚本迁移到ES6模块。客户端代码的常见模式是将跟踪信息推送到 window 对象上的全局数组。一个具体的例子是GTM window.dataLayer数组。

我想将这些全局变量抽象到 ES6 模块中,而不是指示 linter 用 /* global dataLayer */ 忽略它们,因为它使代码更容易理解。我的第一个尝试是创建这样的垫片:

export default window.dataLayer;

但是,如"实现视图"一节中所述,上述代码等效于:

const *default* = window.dataLayer; // *not* legal JavaScript
export { *default* as default };

因此,每个模块中的window.dataLayer数组将是原始window.dataLater数组的副本:当 GTM 异步引导时,它不会看到从模块推送的事件,因为只有本地*default*才会有这些事件。

使用

ES6 模块处理此类全局变量的推荐方法是什么,它不涉及像使用 Proxy 那样的重量级解决方案?在模块化系统中有很多全局变量确实感觉很糟糕。

与您在问题中描述的相反,处理此问题的正确方法是:

/* data-layer.js */
window.dataLayer = [];
export default window.dataLayer;

。任何需要推送到"dataLayer"数组的模块只需要这样的东西:

import dataLayer from 'data-layer';
// ... some code I assume
dataLayer.push({
  'pageCategory': 'signup',
  'visitorType': 'high-value'
});

由于 ES6 导入将只读引用传递给导出,因此它不是要导入的数组的副本,而是在数据层中创建和导出的数组.js。

但是棘手的部分是,您必须修改Google跟踪代码管理器容器代码段,使其在加载后不会立即运行,而是仅在所有可能修改dataLayer脚本运行后运行。

如果要将 GTM 容器代码段作为模块单独加载,则可能需要先导入所有可能修改 dataLater 的脚本(并确保该部分实际运行),然后再调用代码段。

像这样:

/* 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.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXX')
}

但是,你知道这并不是如何做到这一点的真正解释,只是一个想法,我不知道什么不同的东西可能会添加到dataLayer,并且由于您正在转向异步模块模式,因此您必须了解异步运行所有这些脚本将如何改变您使用GTM系统的方式, 这显然是写成使用全局变量同步运行的。

我想知道谷歌是否会很快用现代JavaScript更新这些东西,或者是否有一个更模块化的选项可用。

如果您不知道,我应该提到:

截至今天(2016 年 1 月),许多(大多数)ES6/ES2015 功能(包括模块)在浏览器中不可用,因此您需要某种构建或加载器来使这些东西在浏览器中工作(如 webpack、browserify、stealjs、jspm 或带有 babel 或 tracuer 之类的东西)

http://stealjs.com/可能是最容易上手的。