GWT 书市或 GWT 作为外部图书馆

发布于 2024-10-07 14:23:45 字数 675 浏览 8 评论 0原文

我只是想通过向 DOM 添加脚本标记来加载 GWT(Google Web Toolkit)应用程序,但是因为 GWT 链接器使用 document.write() 我无法找到任何好的方法这样做。我在各种博客文章中发现了一些这样做的技巧,但它们似乎都在最新版本的 GWT 中失败了。有什么合理的非侵入性方法可以做到这一点吗?

说明

在主机 html 页面中启动 GWT 应用程序的正常方式:

<script type="text/javascript" language="javascript" src="myapp.nocache.js"></script> 

当然,页面加载后就会启动。我想稍后再做:

function startapp() {
    var head = document.getElementsByTagName('head');
    var s = document.createElement('script');
    s.setAttribute('type', 'text/javascript');
    s.setAttribute('src', 'myapp.nocache.js');
    head[0].appendChild(s);
}

I simply want to load a GWT(Google Web Toolkit) app by adding a script tag to the DOM, however because the GWT linker uses document.write() I'm unable to find any good way of doing so. I've found some hacks for doing so on various blog posts but they all seem to fail with the latest version of GWT. Any reasonably non-invasive approach for doing this come to mind?

Clarification:

Normal way to start up a GWT app, in your host html page:

<script type="text/javascript" language="javascript" src="myapp.nocache.js"></script> 

This, of course, starts up as soon as the page loads. I want to do it at a later time:

function startapp() {
    var head = document.getElementsByTagName('head');
    var s = document.createElement('script');
    s.setAttribute('type', 'text/javascript');
    s.setAttribute('src', 'myapp.nocache.js');
    head[0].appendChild(s);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

昔日梦未散 2024-10-14 14:23:45

到目前为止,这似乎有效:

将其添加到 App.gwt.xml 的顶部:

<!-- Cross site linker -->
<inherits name="com.google.gwt.core.Core" />
<add-linker name="xs" />

使用上述设置编译应用程序后,修改(或复制)生成的 app.nocache.js,如下所示:

1)注释最后一个$doc.write... 语句

2) 从刚刚注释掉的 $doc.write 语句中复制此部分并对其进行评估。示例:

eval('window.__gwtStatsEvent && window.__gwtStatsEvent({' + 'moduleName:"app", sessionId:window.__gwtStatsSessionId, subSystem:"startup",' + 'evtGroup: "loadExternalRefs", millis:(new Date()).getTime(),' + 'type: "end"});' + 'window.__gwtStatsEvent && window.__gwtStatsEvent({' + 'moduleName:"app", sessionId:window.__gwtStatsSessionId, subSystem:"startup",' + 'evtGroup: "moduleStartup", millis:(new Date()).getTime(),' + 'type: "moduleRequested"});');

3) 紧随其后添加此行。

document.body.appendChild(document.createElement('script')).src=base + strongName + ".cache.js";

因此,您基本上是用这两行替换 $doc.write

现在,您的书签将类似于:

<a href="javascript:(function(){document.body.appendChild(document.createElement('script')).src='http://abc.com/app.nocache.js';})();">My App</a>

Here's what seems to work so far:

Add this to the top of your App.gwt.xml:

<!-- Cross site linker -->
<inherits name="com.google.gwt.core.Core" />
<add-linker name="xs" />

After compiling your app with the above setting, modify (or copy) the generated app.nocache.js as follows:

1) Comment the last $doc.write... statement

2) Copy this portion from the $doc.write statement you just commented out and eval it. Example:

eval('window.__gwtStatsEvent && window.__gwtStatsEvent({' + 'moduleName:"app", sessionId:window.__gwtStatsSessionId, subSystem:"startup",' + 'evtGroup: "loadExternalRefs", millis:(new Date()).getTime(),' + 'type: "end"});' + 'window.__gwtStatsEvent && window.__gwtStatsEvent({' + 'moduleName:"app", sessionId:window.__gwtStatsSessionId, subSystem:"startup",' + 'evtGroup: "moduleStartup", millis:(new Date()).getTime(),' + 'type: "moduleRequested"});');

3) Add this line right after.

document.body.appendChild(document.createElement('script')).src=base + strongName + ".cache.js";

So you're basically replacing the $doc.write with those two lines.

Now, your bookmarklet will look something like:

<a href="javascript:(function(){document.body.appendChild(document.createElement('script')).src='http://abc.com/app.nocache.js';})();">My App</a>
痞味浪人 2024-10-14 14:23:45

我假设您已经在使用跨域链接器,但这并不能解决您的 document.write 问题。如果没有,它可能值得一看(抱歉,没有足够的经验可以说。)

我相当确定可以使用的一种方法是:

您的书签在页面上添加了一个脚本标签(就像现在一样

)脚本不是 GWT 编译器输出。它是一个普通的 javascript,将 IFrame 添加到页面,并且该 IFrame 的 src 指向服务器上加载 GWT 模块的 HTML 页面。

据推测,GWT 模块的目标是从其加载的页面中获取内容。当然,在这种情况下它不能直接执行此操作,因为 IFrame 来自与父页面不同的域。

为了完成这项工作,您必须使用 window.postMessage 和 window.addEventListener 在 IFrame 中的 GWT 模块和父级中的 javascript 存根之间进行通信(在 GWT 端使用 JSNI)。

如果您必须支持旧版浏览器,postMessage 不起作用 - 但你也许可以摆脱散列操作 - 但这可能是我在实用性上划清界限的地方。

I'm assuming you are already using the cross-domain linker and this does not resolve your problem with document.write. If not, it might be worth a look (sorry, not enough experience with it to say.)

One approach that I am fairly sure could be made to work is this:

Your bookmarklet adds a script tag to the page (as now)

This script is not GWT compiler output. It is a plain-old javascript that adds an IFrame to the page, and the src of that IFrame is pointed at an HTML page on your server that loads your GWT module.

Presumably the goal is for your GWT module to get things out of the page it was loaded into. Of course, it can't do this directly in this case because the IFrame comes from a different domain than the parent page.

In order to make this work you would have to use window.postMessage and window.addEventListener to communicate between your GWT module in the IFrame and your javascript stub in the parent (using JSNI on the GWT side.)

If you have to support older browsers, postMessage won't work - but you might be able to get away with hash manipulation - but this is probably where I'd draw a line on practicality.

风为裳 2024-10-14 14:23:45

每当浏览器加载 JavaScript 文件时,它也会执行其中的每一行,以便构建符号表等。

在您的情况下,应用程序会在浏览器中加载,并且在加载 dom 后,您的 GWT 模块 js 会被加载。此时,浏览器将尝试执行 GWT 模块 javascript 的每一行,这可能会导致您之前加载的 DOM 发生混乱。

您的用例到底是什么?如果您的要求是有条件地加载 GWT 模块,那么您可以尝试如下操作:
将其包含在您的脑海中:

<script src="gwtmoduleloader.js"></script>

这里,gwtmoduleloader.js 实际上是一个 servlet,它将保存逻辑以确定是否要加载 gwt 模块。

如果要加载 GWT 模块,sevlet 可以打印 a

document.write('<script src="myapp.nocache.js"></script>') 

或静默返回。

当浏览器评估 gwtmoduleloader.js 的内容时,它可能会找到另一个脚本(在您的情况下是 gwt 模块)的 document.write ,它将加载并评估该脚本。因此,这是一个有条件的负载,可以在身体开始加载之前实现。

这是您要找的吗?

Whenever a browser loads a javascript file, its also execute every line of it inorder to build the symbol tables etc.

In your case, the app loads in the browser and after the dom is loaded, your GWT module js gets loaded. At this point, the browser will try to execute every line of the GWT module javascript, possibly causing your earlier loaded DOM to go for a toss.

What exactly is your use case? If your requirement is conditionally loading the GWT module then your could try something like this:
Include this in your head:

<script src="gwtmoduleloader.js"></script>

Here, gwtmoduleloader.js is infact a servlet that will hold logic to figure out if the gwt module is to be loaded.

If the GWT module is to be loaded, the sevlet can print a

document.write('<script src="myapp.nocache.js"></script>') 

or else return silently.

When browser evaluates the contents of gwtmoduleloader.js, it may find a document.write for another script (in your case the gwt module), which it will load and evaluate. This is thus a conditional load and can be achieved before the body begins loading.

Is this what you were looking for?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文