2012-07-26 35 views
33

我目前正在学习RequireJS基础知识,并对构建配置文件,主要文件以及RequireJS与多页面项目的使用有一些疑问。如何在多页面项目中使用RequireJS构建配置文件+ r.js

我的项目的目录结构如下:

 
httpdocs_siteroot/ 
    app/ 
     php files... 
    media/ 
     css/ 
      css files... 
     js/ 
      libs/ 
       jquery.js 
       require.js 
       mustache.js 
      mains/ 
       main.page1.js 
       main.page2.js 
       main.page3.js 
      plugins/ 
       jquery.plugin1.js 
       jquery.plugin2.js 
       jquery.plugin3.js 
      utils/ 
       util1.js 
       util2.js 
     images/ 

由于这个项目是不是一个单页的应用程序,我会为每个页面创建一个单独的主文件(尽管一些网页使用相同的主文件)。

我的问题是:

  1. 是RequireJS甚至实际为不是单页的项目?

  2. 不使用的优化,我的每一个主文件启动以基本相同的配置选项:

    requirejs.config({ 
        paths: { 
        'jquery': 'http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min' 
        }, 
        baseUrl: '/media/js/', 
        // etc... 
    }); 
    require(['deps'], function() { /* main code */ }); 
    

    是否有办法避免这种情况?像每个主文件都包含相同的构建配置文件而不必实际构建它?

  3. r.js应该去httpdocs_siteroot的父目录吗?

  4. 我的应用程序目录结构或使用RequireJS有什么明显的错误吗?

+0

我有和简短的答案,但我需要一些细节:多少页?每个页面特定的代码很少或很多代码(比如,每个页面代码为10kb)? – devundef 2012-07-29 09:58:11

+0

你使用的是requirejs插件,插件是什么? – devundef 2012-07-29 10:00:32

+0

通常每个mainjs文件<10kb。我只是将它用于初始化jquery插件之类的东西。将会有很多页面......我会说20并且在不断增长。所以可能大约有15个mainjs文件和增长。我使用的插件是jquery插件,并使用define调用包装以符合AMD标准 – AndyPerlitch 2012-07-29 16:27:44

回答

57

首先,这不是一个独特的解决方案的问题。我将解释我使用RequireJS的方式,它适用于我,并可能适合你:)

二,英语不是我的母语。有关该语言的更正和提示将非常感谢。随意,球员:)

1)是否需要JS甚至实际为不是单页的项目?

这取决于。例如,如果你的项目在页面之间没有共享代码,RequireJS的帮助将是适度的。 RequireJS的主要思想是将应用程序模块化为可重用代码的块。如果你的应用程序只使用页面特定的代码,那么使用RequireJS可能不是一个好主意。

2)不使用优化器,我的每个主文件都以基本相同的配置选项开始。有没有办法避免这种情况?像每个主文件都包含相同的构建配置文件而不必实际构建它?

我看到正在对主文件的配置,或创建一个模块,将配置RequireJS,然后使用该模块作为main.js.第一依赖的唯一途径但这可能会很棘手。我的应用程序中不使用许多main.js文件;我只使用一个充当装载程序的应用程序(请参见下文)。

3)r.js是否应该进入httpdocs_siteroot的父目录?

不一定。你可以把它放在/ media目录中,因为你所有的客户端都在那里。

4)我的应用程序目录结构或使用requirejs有什么明显的错误吗?

我不会那么说。另一方面,结构可能有点过于分散。例如,你可以把所有的'第三方东西'放在一个/ vendor目录中。但这只是糖;你的结构将运作良好,看起来是正确的。我认为主要问题是多个主文件中的requirejs.config()调用。

我现在有同样的问题,我结束了以下解决方案:

1)不要用规定的包装不符合要求的AMD-文件。尽管它起作用,但您可以使用requirejs.config中的“shim”属性(请参见下文)获得相同的结果。

2)在多页面应用程序中,我的解决方案是不要求优化的main.js文件中的页面特定模块。相反,我需要从主文件中获取所有共享代码(第三方和我自己的代码),并在每个页面上加载页面特定的代码。主文件最终只是一个加载器,在加载所有共享/ lib文件后启动特定于页面的代码。

这是我用它来建立与requirejs一个多页应用的样板

目录结构:

/src目录 - 我把所有的客户端的东西一个src目录里面,所以我可以运行该目录内的优化器(这是您的媒体目录)。

/src/vendor - 这里我放置所有第三方文件和插件,包括require.js。

/src/lib - 在这里,我放置了由整个应用程序或某些页面共享的所有自己的代码。换句话说,不是页面特定的模块。

/src/page-module-xx - 然后,我为每个页面创建一个目录。这不是一个严格的规定。

/src/main.js:这是整个应用程序的唯一主文件。它将:

  • 配置RequireJS,包括垫片
  • 负载共享库/模块
  • 负载特定页面的主模块

这是一个requirejs.config呼叫的例子:

requirejs.config({ 
     baseUrl: ".", 
     paths: { 
      // libraries path 
      "json": "vendor/json2", 
      "jquery": "vendor/jquery", 
      "somejqueryplugion": "vendor/jquery.somejqueryplufin", 
      "hogan": "vendor/hogan", 

      // require plugins 
      "templ": "vendor/require.hogan", 
      "text": "vendor/require.text" 
     }, 
     // The shim section allows you to specify 
     // dependencies between non AMD compliant files. 
     // For example, "somejqueryplugin" must be loaded after "jquery". 
     // The 'exports' attribute tells RequireJS what global variable 
     // it must assign as the module value for each shim. 
     // For example: By using the configutation below for jquery, 
     // when you request the "jquery" module, RequireJS will 
     // give the value of global "$" (this value will be cached, so it is 
     // ok to modify/delete the global '$' after all plugins are loaded. 
     shim: { 
      "jquery": { exports: "$" }, 
      "util": { exports: "_" }, 
      "json": { exports: "JSON" }, 
      "somejqueryplugin": { exports: "$", deps: ["jquery"] } 
     } 
    }); 

然后,配置完成后,我们可以做出第一个require()请求 为所有这些库,然后做我们的“页面主”模块的请求。

//libs 
require([ 
    "templ",  //require plugins 
    "text", 
    "json",  //3rd libraries 
    "jquery", 
    "hogan", 
    "lib/util" // app lib modules 
], 
    function() { 
     var $ = require("jquery"), 
      // the start module is defined on the same script tag of data-main. 
      // example: <script data-main="main.js" data-start="pagemodule/main" src="vendor/require.js"/> 
      startModuleName = $("script[data-main][data-start]").attr("data-start"); 

     if (startModuleName) { 
      require([startModuleName], function (startModule) { 
       $(function(){ 
        var fn = $.isFunction(startModule) ? startModule : startModule.init; 
        if (fn) { fn(); } 
       }); 
      }); 
     } 
    }); 

正如您在上面require()的主体中看到的那样,我们期待require.js脚本标记的另一个属性。 data-start属性将保存当前页面的模块名称。

因此,在HTML页面上,我们必须增加这些额外的属性:

<script data-main="main" data-start="pagemodule/main" src="vendor/require.js"></script> 

通过这样做,我们将结束与优化main.js一个包含“/供应商”和“所有文件/ lib“目录(共享资源),但不包括页面特定的脚本/模块,因为它们在main.js中没有作为依赖关系进行硬编码。页面特定模块将在应用程序的每个页面上分别加载。

“页面主”模块应返回function(),将由上面的“应用程序主”执行。

define(function(require, exports, module) { 
    var util = require("lib/util"); 

    return function() { 
     console.log("initializing page xyz module"); 
    }; 
}); 

编辑

下面是例子,你如何使用的建造轮廓,以优化有一个以上的文件中的特定页面模块。

例如,假设我们有以下页面模块:

/page1/main.js

/page1/dep1.js

/page1/dep2.js

如果我们不优化这个模块,那么浏览器会发出3个请求,每个脚本都有一个请求。 我们可以通过指示r.js创建一个包并包含这3个文件来避免这种情况。

在建造轮廓的“模块”属性:

... 
"modules": [ 
    { 
     name: "main" // this is our main file 
    }, 
    { 
     // create a module for page1/main and include in it 
     // all its dependencies (dep1, dep2...) 
     name: "page1/main", 
     // excluding any dependency that is already included on main module 
     // i.e. all our shared stuff, like jquery and plugins should not 
     // be included in this module again. 
     exclude: ["main"] 
    } 
] 

通过这样做,我们创建了具有所有依赖另一个单页主文件。但是,由于我们已经有一个主文件可以加载我们所有的共享内容,因此我们不需要再将它们包含在page1/main模块中。 该配置有点冗长,因为您必须为每个页面模块执行此操作,而您有多个脚本文件。

我上传了GitHub中的样板代码:https://github.com/mdezem/MultiPageAppBoilerplate。 这是一个正在运行的样板,只需为节点安装node和r.js模块并执行build.cmd(位于/ build目录中,否则将失败,因为它使用相对路径)

我希望我已经清楚。让我知道是否听起来有点奇怪;)

问候!

+0

感谢您的出色答案!我还需要再读几遍,看看你的github样板文件才能真正得到它,但我相信我会很快提出一些问题! – AndyPerlitch 2012-07-31 00:08:09

+0

@AndyPerlitch,很高兴知道,感谢您的修改。 – devundef 2012-07-31 22:16:08

+0

您是否在每个需要与DOM交互的页面模块中使用$(document).ready()函数?所以它看起来像: 定义( 函数(){ 恢复功能(){ $(文件)。就绪(函数(){// 做的东西 });} } ); 似乎有点冗长......你可以把需要的脚本放在页面的末尾吗?我不知道,因为我知道require文档要求将它放在头部 – AndyPerlitch 2012-08-03 17:45:46

1
<script data-main="js/main" src="js/lib/require.js"></script> 


// file: js/main 

require(['./global.config'], function(){ 
    require(['./view/home'], function() { 
     // do something 
    }); 
}); 

这是我在我的项目中使用的。

相关问题