自定义或完全跳过 GWT 的最佳方法是什么 *.nocache.js

What is the best way to customize or entirely skip GWT's *.nocache.js

这是交易 - 我们只有一个排列,因此无需执行任何浏览器检测。我们正在针对移动设备进行优化,延迟和网络带宽是一个问题。除了使用 HTTP 请求之外,我们还有另一种获取主要片段的方法,我们想利用它,但 *.nocache.js 只知道创建一个通过 http 请求它的脚本标记。

我正在尝试创建 *.nocache.js 的自定义版本(目前正在破解),它将进行足够的设置以允许我们以不同的方式加载片段代码(因为直接加载片段不会似乎工作,即使我取消转义它 - 所有代码都在传递给函数调用的引用字符串列表中)。我设法获得了该代码 运行 但它失败了。

有什么想法吗?

好吧,在上面 Thomas Broyer 的评论之后,我能够更进一步并找到(目前)明确的答案:"This is NOT possible cleanly."(无需编写自定义链接器)......但是有一个我仍在进一步追求的不太干净的方式。

具体来说,有三个官方 GWT 链接器,其中两个生成的代码本身想要通过 http 请求主代码片段。第三个 "sso" 生成一个文件,并且只适用于一个排列(在我的情况下是可以接受的)。但是,生成的代码会执行 document.write(),这会在动态调用时删除宿主文档。

它这样做是为了在它预期来自的标记之后创建一个标记标记,以便它可以从中提取自己的 URL 和脚本基础 URI。在我的例子中,主机页面位于 GWT 模块文件夹的父文件夹中,通常包含如下内容:

<script ... src="moduleName/moduleName.nocache.js"></script>

... 和 moduleName.nocache.js 想找出所有其他与模块相关的请求(例如其他代码碎片等)。

在任何情况下,如果它找不到用 document.write() 写入的标记标签,它将尝试查找标签并改用它。问题是,该标签既不存在也不正确——在我们的例子中,它会引用所需内容的父级。然而,这个标签也可以在我们实际注入之前动态插入 moduleName.nocache.js... 然后在注入后更正回来。

类似于:

      // Obtain the main fragment script code using alternate means:
      var scriptCode = ...;

      // Create the script tag for the main code fragment
      var codeElement = document.createElement("script");
      codeElement.type = "text/javascript";
      
      // Prepare the environment to run it, to hack around
      // its document.write and base URI needs.
      
      // First remember the normal/original document.write method:
      var originalWriteMethod = document.write;
      
      // ... and replace it with a dummy one (we'll put this back later):
      document.write = function() {}
      
      // ... and also remember the document base
      var originalBase = document.baseURI;
      
      // Figure out the script base based on the originalBase:
      var scriptBase = originalBase + "moduleName/";
      
      // Failing document.write case, the main code fragment will look for
      // the last <base> tag to get the script base. Add that element and
      // set it to reference the scriptBase (we'll have to undo this later):
      var baseElement = document.createElement("base");
      baseElement.href = scriptBase;
      document.head.appendChild(baseElement);
      
      // Different browsers work differently...  try to cover two cases:
      try {
        codeElement.appendChild.document.createTextNode(scriptCode);
        document.head.appendChild(codeElement);
      } catch (e) {
        codeElement.text = scriptCode;
        document.head.appendChild(codeElement);
      } finally {
        // Whatever case occurred above, we must return the document.write()
        // to normal implementation and undo our temporary document base 
        // change:
        document.write = originalWriteMethod;
        baseElement.href = originalBase;
      }

这会获取 "load"、初始化和 运行 的代码。我还有更多测试要做,但这是我迄今为止最接近的测试。