没有带有由Closure Compiler编译的es6模块库的导出符号

时间:2017-09-07 09:07:55

标签: javascript ecmascript-6 google-closure-compiler es6-modules

起点:Closure Compiler(ADVANCED_OPTIMIZATIONS级别)在单个库文件中成功编译了许多js文件(没有警告/错误)。

在这些js文件中:

  • ListViewgoog.require用于导入/导出它们之间的内容
  • 库中需要
  • goog.provide/** @export */(const / function / Class / var)前面使用。

某些HTML文件包含库和一些未编译的js成功访问此库中定义的所有whatever

我想要的:转到es6模块语法

我为每个js文件做了什么:

  • whatever替换为goog.require,其中包含Class,from另一个js文件的函数列表
  • import已删除,goog.provide已添加到其他js文件所需的每个类,函数等前面
  • 尝试1:图书馆外每次export都不需要更改/** @export */
  • 尝试2:所有whatever替换为/** @export */ whatever

这是成功编译的(没有警告/错误,仍处于ADVANCED_OPTIMIZATIONS级别)。

问题:现在,对于相同的HTML文件,浏览器会看到库中定义的所有goog.exportSymbol('whatever', whatever)都是“未定义的”。实际上,当我在控制台中键入whatever时,我可以看到编译器更改了所有符号名称(Object.keys( window )aaba等),但我没有导出符号ca

示例:whatever是库中定义的demoVisitors,需要在外部。 在库文件之前,我可以看到const array,并且内容在HTML页面中正确显示。更改es6模块后,我可以看到... w("demoVisitors",[Oa,La,Ma,Na]); ...... H("demoVisitors$$module$filemane",Oa); ...是其中filename已定义的文件名)对于尝试1而demoVisitors对于尝试2 H("demoVisitors",[Na,Ka,La,Ma]);在同一页面的浏览器中未定义。

1 个答案:

答案 0 :(得分:1)

经过进一步调查,我找到了解决方案。

虽然在浏览器中加载时没有任何错误(当然除了undefined whatever),但是我的库没有被执行。我只是将闭包库移到要编译的文件堆栈之前,然后浏览器正确执行我的库,并正确导出我的符号。有关详细信息,请参见下文。

导出符号的3种方法在编译的es6模块中有效:/** @export */ whatevergoog.exportSymbol('whatever', whatever)window['whatever'] = whatever。前两个是第三个方便(根符号)。

尽管如此/** @export */ myClass会产生一些不友好的未经混淆的名称,例如myClass$$module$source-filename-with-path。 要获取未经模糊处理的名称myClass,请避免在我的代码中使用goog函数并巧妙地启用已编译/未编译模式,我删除/** @export */并在{{1}之后添加unobfuscateSymbol('myClass', myClass) }}。这是我的“自己的”函数,它直接受到闭包库中定义的class myClass { ... }函数的启发。这只适用于像类这样的根符号,您可以为类中定义的所有符号(属性,函数等)保留exportSymbol

以下是源代码:

/** @export */

我如何详细确定问题:

  1. 为了理解导出问题,我尝试在闭包库中定义的exportSymbol函数中放置一个断点,同时在浏览器中加载我的HTML测试页面:没有中断......

  2. 我通过添加console.log(“我的库正在执行”)仔细检查了这个执行问题:我能够看到export function unobfuscateSymbol(publicPath, object, objectToExportTo = window) { // Same code can be used compiled and not compiled so unobfuscation only in case of obfuscation if (unobfuscateSymbol.name !== 'unobfuscateSymbol') { const /** Array<string> */ parts = publicPath.split('.'); let /** Object */ objToExportTo = objectToExportTo; let /** string */ part; const /** number */ nbOfParts = parts.length; for (let /** number */ i = 0; i < nbOfParts; i += 1) { part = parts[i]; if ((i === (nbOfParts - 1)) && object) { objToExportTo[part] = object; } else if (objectToExportTo[part] && objectToExportTo[part] !== Object.prototype[part]) { objToExportTo = objectToExportTo[part]; } else { objToExportTo[part] = {}; objToExportTo = objToExportTo[part]; } } } } / goog.require版本中的消息我的库,但不在es6 goog.provide / import版本中。当然,没有执行,没有符号导出。

  3. 我用IIFE包装了我的图书馆。 Closure编译器参数:export和我的库中的执行错误消息出现在浏览器控制台中。我发现在休息时间{Cl}库的基本命名空间--output_wrapper "(function(){%output%})()"goog.global

  4. 我将闭包库移到要编译的文件堆栈之前。关闭编译器参数:undefined以确保编译的–js closure-lib-path/base.js –js myfile1.js –js myfile2.js …内容在第一个goog编译生成的exportSymbol调用之前。

  5. 然后在浏览器中执行和导出就可以了。我刚刚添加了/** @export */函数,如上所述,以获得与我的库的unobfuscateSymbol / goog.require版本相同的友好导出名称。