【问题标题】:How can I load my own js module with goog.provide and goog.require?如何使用 goog.provide 和 goog.require 加载我自己的 js 模块?
【发布时间】:2010-12-27 12:01:27
【问题描述】:

我们正在尝试将项目的包装从 dojo 切换到 google 关闭,但到目前为止我们还没有运气。下面是一个简单的示例,说明了我们要完成的工作:

<html xmlns="http://www.w3.org/1999/xhtml"> <head> <script type="text/javascript" src="runtime/src/core/lib/goog-rev26/base.js"></script> <script> goog.require("foo.bar"); function main() {foo.bar.echo("hello world")} </script> </head> <body onload="main()"> </body> </html>

然后在/foo/bar.js 我有:


goog.provide("foo.bar");
foo.bar.echo = function(s) {console.debug(s);}

我在firebug中收到的错误如下:

goog.require 找不到:foo.bar foo 未定义

当我查看“网络”选项卡时,没有用于获取文件的 http 请求 - 我期待闭包库生成一个脚本标记来获取 bar.js。

帮助! ;)

【问题讨论】:

    标签: javascript dojo google-closure google-closure-library


    【解决方案1】:

    解决方案:

    • 将闭包下载到您的项目外部(或资产等)。

    • 不必费心设置 onload、延迟、异步播放等。

    • 它们不起作用(它们的设计模式也很差,而且非常蹩脚..)

    - 这是您的main.js,您可以在其中将代码动态注入 DOM(例如创建书签或其他东西):

    /**
     * loads the base.js of google closure.
     * http://code.google.com/p/closure-library/
     */
    
    (function() {
      var s = document.createElement('script');
      s.type = "text/javascript";
      s.src = "./assets/closure/goog/base.js";
      s.async = true;
      document.getElementsByTagName("body")[0].appendChild(s);
    }());
    
    /**
     * activated from the base.js as JSONProtocol.
     */
    window['starter'] = function() {
      console.log("hi...");
    };
    

    现在:

    • 编辑你的base.js

    添加文件末尾

    ......
    .......
    ........
    
    /**
     * run the method when done load. just like JSONProtocol.
     */
    window.setTimeout(function() {
      window['starter']();
    }, 5);
    
    • 您的“回调”只是在文件完成渲染后激活启动器,

    • 它运行良好,并且持续异步加载每个资源。

    附言

    1. window['....'] 语法使您可以安全地最大限度地使用闭包编译器并始终使用相同的名称(尽管还有其他方法可以这样做,但这是简单的“始终有效” " 方式..)。

    2。在base.js 上,您也可以避免超时而直接使用

    ......
    .......
    ........
    
    /**
     * run the method when done load. just like JSONProtocol.
     */
    window['starter']();
    

    但根据经验,现代浏览器在包装那些“无关紧要,只在最后做这些事情,比如 JSONProtocol 回调”的事情时会表现得更好 -

    超时(通常与 0-5 的值一起使用)不会作为超时中断,而是作为打破代码块同步性的一种方式,允许真正的“上下文切换”行为。

    虽然那里有额外的开销。

    【讨论】:

    • 我不太明白这与加载包有什么关系(例如,将模块名称映射到文件名)
    【解决方案2】:

    是的,您应该使用 calcdepds.py。经过多次反复试验,我创建了一篇大型博客文章,以找出最好的方法,我还讨论了 dojo.require 和 goog.require 之间的区别:

    http://apphacker.wordpress.com/2009/12/28/howto-how-to-use-goog-require-and-goog-provide-for-your-own-code/

    【讨论】:

    • 是的,我没有继续为我的 wordpress 域付费。现在是apphacker.wordpress.com/2009/12/28/…,但不推荐使用 calcdeps.py。闭包库存储库中有更好的构建工具,它们打破了 calcdeps 过去所做的事情。
    【解决方案3】:

    让自定义模块工作的任何一种方式,至少对于开发版本,都是在 google 的 base.js 文件包含之后,在 html 页面的 head 部分手动包含 js 文件。

    <script type="text/javascript" src="js/closure/goog/base.js"></script>
    <script type="text/javascript" src="js/closure/custom/custom.js"></script>
    <script type="text/javascript" src="js/closure/custom/sub/sub.js"></script>
    ...
    

    但是,您应该自己关心包含顺序。对于不是很大的自定义文件集,它工作得很好。对于生产版本,您仍然最好使用 js 源代码编译来获得闭包库的所有好处。

    【讨论】:

      【解决方案4】:

      更新!!!

      新版本的 calcdeps.py 稍微改变了游戏。要创建 deps.js,您现在需要使用 -d 标志。例如:

      python path-to-closure-library/closure/bin/calcdeps.py -i path-to-your-src/requirements.js -o deps -d path-to-closure-library/closure/ -p path-to-your-src/ --output_file=path-to-your-src/deps.js
      

      编译:

      python path-to-closure-library/closure/bin/calcdeps.py -i path-to-your-src/requirements.js -d path-to-closure-library/closure/ -p ./ --output_file=path-to-your-release/scripts.min.js -c path-to-compiler/compiler.jar -f "--compilation_level=ADVANCED_OPTIMIZATIONS" -f "--debug=true" -f "--process_closure_primitives=true" -f "--manage_closure_dependencies=true" -o compiled
      

      所以现在这个过程实际上要容易得多,但你必须使用你的 ESP 能力来发现它完全没有记录。 calcdeps.py 现在也不能在 Windows 上与 Python 3.1 一起使用,所以这也很有趣。一些 hack 让它对我有用(我不会放在这里,因为我不是 python 程序员,必须有更好的方法来做到这一点)。

      总的来说,最后一天非常有趣,希望这篇文章能帮助人们避免同样的享受。

      圭多

      【讨论】:

        【解决方案5】:

        这是我一直在做的一个小项目,可能对你有帮助:http://github.com/fintler/lanyard

        查看 build.xml、名为 lanyard.js 的文件以及位于 src/geom/* 中的所有文件。

        build.xml 中有一个示例,说明如何通过 ant 为 src 中的所有 js 调用 calcdeps.py。这可能不是最好的做事方式,但到目前为止它一直对我有用。

        【讨论】:

          【解决方案6】:

          我想通了,这并不难,但有一些陷阱。

          基本上,您可以在以下几种模式之一中使用依赖生成脚本 calcdeps.py (you should read calcdeps.py docs):

          1. 生成 deps.js 文件
          2. 将所有内容连接到一个文件中,可选择使用闭包编译器对其进行编译。

          对于开发,您应该使用 (1),因为它允许您在编辑 JS 源代码后不运行 calcdeps.py,除非您更改依赖关系树。剩下的答案是关于这种方式的,我还没有尝试过另一种。

          这是我为生成它所做的:

          #!/bin/bash
          cd closure-library/closure/goog
          python ../bin/calcdeps.py -p ../../../js -o deps > ../../../my-deps.js
          

          ...假设以下目录结构:

          project/
            closure-library/ (as checked out from SVN)
            js/ (my JS code)
            app.html
          

          (-p参数遍历指定目录下的所有js文件,文档说如果需要可以指定多个目录进行搜索。)

          上面的调用在主 app.html 旁边创建了一个 my-deps.js 文件,我用它来运行应用程序。创建的文件在js/ 中包含有关我的 JS 文件的信息,如下所示:

          goog.addDependency('../../../js/controllers.js', ['proj.controllers'], []);
          goog.addDependency('../../../js/ui.js', ['proj.ui'], ['proj.controllers']);
          

          - 第一个字符串是我的 JS 文件的路径相对于closure-library/closure/goog/base.js(这很重要!),第二个数组是 @ 的列表987654330@-d 字符串,最后一个数组是goog.require-d 字符串的列表。

          现在在 app.html 我有:

          <script src="closure-library/closure/goog/base.js"></script>
          <script src="my-deps.js"></script>
          <script>
            goog.require("proj.ui");
          </script>
          <script>
            // here we can use the required objects
          </script>
          

          注意:

          1. 除了包含闭包的 base.js 之外,我还包含了我生成的 deps.js
          2. 正如教程the goog.require call has to be in a separate script tag中提到的那样,因为它附加了一个脚本标签来加载所需的脚本,并且在当前脚本标签完成处理后加载它们。

          陷阱:

          1. 上述路径与 base.js 相关的问题。 goog.require 通过连接 base.js 基本 URL(即没有 base.js 叶名)和 deps.js 中 goog.addDependency 的第一个参数来创建要加载的脚本 URL。
          2. calcdeps.py 在 Windows 上运行不佳,尤其是 using the backslashes in the deps.js string literals
          3. 如果出现问题,您可能需要查看all issues mentioning calcdeps 并确保您的结帐是最新的。

          【讨论】:

            【解决方案7】:

            我可以通过将以下内容添加到 deps.js 来使其工作:
            goog.addDependency('../../../foo/bar.js', ['foo.bar'], []);

            Firefox 现在会在遇到 goog.requires 语句时向 /foo/bar.js 发出 http 请求。

            但是,该文件包含以下注释:
            // This file has been auto-generated by GenJsDeps, please do not edit.

            根据this,GenJsDeps 与calcdeps.py 相同。如果您查看文档,似乎有一个 -o deps 开关,它将重新生成 deps.js,因此它不是手动编辑的。

            【讨论】:

            • 你应该使用 calcdeps.py 而不是自己使用 addDepedency。
            • addDependency 在你想开发的时候很有用。 Closure Compiler 每次编译都会占用大量时间。
            猜你喜欢
            • 1970-01-01
            • 2018-01-31
            • 1970-01-01
            • 2020-02-29
            • 2018-03-15
            • 2022-12-12
            • 2017-09-14
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多