4

所以,我有一个使用 requireJS 的应用程序。挺开心的。在大多数情况下。

这个应用程序使用了 Socket.IO。Socket.IO 由 nodejs 提供,并且不在与主网络服务器相同的端口上运行。

为了解决这个问题,在我们的主 js 文件中,我们执行以下操作:

    var hostname = window.location.hostname;
    var socketIoPath = "http://" + hostname + ":3000/socket.io/socket.io";
    requirejs.config({
        baseUrl: "/",
        paths: {
            app           : "scripts/appapp",
            "socket.io"   : socketIoPath
        }
    });

比这更复杂,但你明白了要点。

现在,在交互模式下,这可以游泳。

当我们尝试使用 r.js 编译它时,丑陋就开始了(技术上我们使用 grunt 来运行 r.js,但这不是重点)。

在 r.js 的配置中,我们为 socket.io 设置了一个空路径(以避免它无法拉入),并将我们的主文件设置为 mainConfigFile。

编译器对此大喊大叫,说:

Running "requirejs:dist" (requirejs) task
>> Error: Error: The config in mainConfigFile /…/client.js cannot be used because it cannot be evaluated correctly while running in the optimizer. Try only using a config that is also valid JSON, or do not use mainConfigFile and instead copy the config values needed into a build file or command line arguments given to the optimizer.
>>     at Function.build.createConfig (/…/r.js:23636:23)

现在,据我所知,这是因为我使用变量来设置“socket.io”的路径。如果我把它拿出来,需要运行得很好,但我不能从服务器运行原始文件。如果我离开它,我的调试服务器很高兴,但构建会中断。

有没有一种方法可以让我在运行时懒惰地分配“socket.io”的路径,这样它就不必进入 requirejs.config() 方法?

4

1 回答 1

2

编辑:对此做了一些广泛的研究。这是结果。

通过构建可以使用 RequireJS 从 CDN 加载。但是,如果您使用的是较小的杏仁装载机,这是不可能的

这使您有两个选择:

  1. 在构建中使用 almond 以及文件的本地副本。
  2. 使用完整的require.js加载器并尝试使用 CDN。
  3. 仅为该资源使用<script>标签。

我说尝试#2,因为有一些警告。您需要require.js在 HTML 中包含data-main构建文件的属性。但是如果你这样做了,require并且define会是全局函数,允许用户对require你的任何内部模块和他们乱搞。如果你对此没问题,你需要在你的构建配置中遵循“空:方案”(但不是在你的主配置中)。

但事实仍然是您现在有另一个 HTTP 请求。如果您只需要一个包含require.js加载程序的构建文件,则只需针对一个文件进行优化

现在,如果你想避免用户使用require你的模块,你必须wrap:true在你的构建中做一些类似的事情。但据我所知,一旦你的模块从 CDN 下来,如果它是 AMD,它会寻找一个全局define函数来注册自己,而这将不存在,因为它现在被包裹在一个闭包中。

我从中吸取的教训是:将资源内联到构建中。这说得通。您减少 HTTP 请求,将其全部缩小并获得 gzip 压缩。您不会将您的模块暴露给世界,一切都会简单得多。如果你正确地缓存你的资源,你甚至不需要担心它。

但由于新版本的 socket.io 不喜欢 AMD,我就是这样做的。确保<script>在 requirejs 之前包含 socket.io 标记。然后创建一个 requirejs 模块,命名socket.io为以下内​​容:

define([], function () {
  var io = window.io;
  window.io = null;

  return io;
});

像这样设置路径:'socket.io': 'core/socket.io'或任何你想要的地方。

并像往常一样要求它!构建以这种方式工作正常。


原始答案

您是否可以使用RequireJS API 中指定的路径配置回退?也许您可以将文件保存在本地作为后备,以便您的构建工作。

socket.io GitHub 存储库指定您可以使用 socket.io-client 包的 dist/ 目录中的文件为客户端提供服务。

于 2013-04-30T01:40:52.020 回答