Javascript 有没有办法用RequireJS惰性地设置资源的路径?

Javascript 有没有办法用RequireJS惰性地设置资源的路径?,javascript,requirejs,Javascript,Requirejs,所以,我有一个应用程序,使用的是requireJS。非常高兴。大部分情况下 此应用程序使用Socket.IO。Socket.IO由nodejs提供,与主Web服务器不在同一端口上运行 为了解决这个问题,在我们的主js文件中,我们做了如下操作: var hostname = window.location.hostname; var socketIoPath = "http://" + hostname + ":3000/socket.io/socket.io"; requ

所以,我有一个应用程序,使用的是requireJS。非常高兴。大部分情况下

此应用程序使用Socket.IO。Socket.IO由nodejs提供,与主Web服务器不在同一端口上运行

为了解决这个问题,在我们的主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设置了一个空路径(以避免它无法拉入),并将主文件设置为maincigfile

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

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”的路径。如果我去掉这个,require运行得很好,但是我不能从服务器上运行raw。如果我离开它,我的调试服务器会很高兴,但构建会中断


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

Edit:对此做了一些广泛的研究。以下是结果

通过构建,可以使用RequireJS从CDN加载。但是,如果您使用的是较小的Almond loader

这给您留下了两个选择:

  • 在构建中使用almond和文件的本地副本
  • 使用完整的
    require.js
    加载程序并尝试使用CDN
  • 仅为该资源使用
    标记
  • 我说试试2,因为有一些警告。您需要在HTML中包含
    require.js
    ,并为生成的文件使用
    datamain
    属性。但是如果您这样做,
    require
    define
    将是全局函数,允许用户
    require
    任何内部模块并对它们进行处理。如果您对此没有意见,那么您需要在构建配置(但不是在主配置)中遵循

    但事实仍然是,您现在有另一个HTTP请求。如果您只需要一个构建文件,其中包括
    require.js
    加载程序,则需要

    现在,如果您想避免用户能够
    要求
    您的模块,您必须在构建中执行类似于
    wrap:true
    的操作。但据我所知,一旦您的模块从CDN中卸下,如果它是AMD,它将寻找一个全局
    define
    函数来注册它自己,而这将不存在,因为它现在被包装在一个闭包中

    我从中吸取的教训是:将资源内联到构建中。这是有道理的。您可以减少HTTP请求,缩小所有请求并获得gzip压缩。您不需要向世界公开您的模块,而且一切都要简单得多。如果你正确地缓存了你的资源,你甚至不需要担心它

    但是,由于新版本的socket.io不喜欢AMD,下面是我如何做到的。确保在requirejs之前包含socket.io
    标记。然后创建一个名为
    socket.io
    的requirejs模块,包含以下内容:

    define([], function () {
      var io = window.io;
      window.io = null;
    
      return io;
    });
    
    按如下方式设置路径:
    'socket.io':'core/socket.io'
    或任意位置

    并要求它像平常一样!这样的构建工作得很好


    原始答案 您是否可以使用RequireJSAPI中指定的?也许您可以将该文件保存为本地备用文件,以便构建工作正常

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