9

我知道这个问题经常以类似的方式出现,但似乎没有解决方案完全符合我的需求。我有以下问题:

在开发中,我使用多个 JS 文件(每个“对象”一个文件)。这些 JS 文件相互之间有几个依赖关系 - 有些依赖于其他文件,我需要先加载它们。目前我使用RequireJS以正确的顺序加载每个JS文件,所以我为每个文件定义了一个模块。很好,花花公子。但现在我想将我所有的 JS 文件连接成一个大 JS 文件,它应该是一个模块本身。我使用 RequireJS 优化器 r.js 来做到这一点。我的问题:每个 JS 文件都连接到一个大的 JS 文件,但是每个对象的模块定义都包含在其中。我没有一个大文件中有一个大模块,而是一个大文件中有很多模块。

之后,我尝试了 grunt 进行连接,效果很好,但忽略了文件的依赖关系。它只是按字母顺序连接每个文件,或者我必须在我的 gruntfile 中硬编码顺序。

我该如何解决这个问题?

就像我的问题的一个例子:我有以下文件(伪代码):

FileA
- define FileA module
- depends on FileB
- FileA Logic

FileB
- define FileB module
- FileB Logic

我想要这个输出:

LibFile
- define LibFile module
- FileB Logic, FileA Logic

但是我用 r.js 得到了这个(从 FileA 和 FileB 复制模块定义):

LibFile
- define FileB module
- FileB Logic
- define FileA module
- depends on FileB
- FileA Logic

我用咕噜声(错误的顺序)得到这个:

LibFile
- FileA Logic
- FileB Logic

也许这个问题有点愚蠢,但我无法用每个人似乎都在使用的工具来解决这个问题……我也尝试了 grunt-requirejs 插件。但它抛出了几个我无法解决的错误。

谢谢你,皮波

4

1 回答 1

7

我要把它变成一个答案。只是这样代码更清晰一些。

我是凭记忆做这些的(因为我现在无法测试)所以有些小事情可能并不完全准确。

这当然取决于您如何打包模块,但一种方法是将所有较小的模块注册到一个更大的模块中:

文件 A.js

define([], function() {
    // do something
    return A;
});

文件 B.js

define(['path/to/A'], function(A){
    // do something with A and more
    return B;
});

然后,将它们打包在一起:

文件 mylib.js

define(['path/to/A', 'path/to/B'], function(A, B){
    return {
        A : A,
        B : B
    }
}

然后你可以将你的构建配置文件指向mylib.js它,它将被合并到一个大文件中。它不会是一个全封装模块,但它会有一个引用其他所有内容的入口模块。然后你可以像这样使用它:

require.config({
    paths : {
        'path/to/mylib' : 'real/path/to/mylib/on/server'
    }
});
require(['path/to/mylib'], function(Lib) {
    // do something using Lib.A or Lib.B
}

要注意的一件事是您的大模块文件的 ID。默认情况下,RequireJS 构建会提供与物理路径匹配的 ID(来自appDirIIRC),并且您必须在加载依赖项时匹配该 ID。简而言之,如果您的结果 mylib.js文件有一个接收 name 的主模块'path/to/mylib',您将必须匹配它并通过相同的 ID 加载它(使用require.config.paths)或使用地图等(其中一些需要 RequireJS 2.0)。

以下是我问你为什么要做“大模块”这件事的原因

另一件值得注意的事情是,如果 mylib.js 已加载,您所有内部较小的模块也会收到与其物理路径匹配的 ID,并且您可以在使用大包模块时使用这些 ID(这样您不仅可以通过 访问它们Lib.A):

require(['path/to/A'], function(A) {
    // do something using A
}
于 2012-06-09T02:48:09.010 回答