如何在多页面项目中使用RequireJS构建配置文件+ r.js. [英] How to use RequireJS build profile + r.js in a multi-page project

查看:94
本文介绍了如何在多页面项目中使用RequireJS构建配置文件+ r.js.的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am currently learning RequireJS fundamentals and have some questions regarding a build profile, main files, and use of RequireJS with multi-page projects.

我项目的目录结构如下:

My project's directory structure is as follows:


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/

由于这个项目不是单页应用程序,我每个都有一个单独的主文件页面(虽然有些页面使用相同的主文件)。

Since this project is not a single-page app, I have a separate main file for each page (although some pages use the same main file).

我的问题是:


  1. RequireJS是否适用于项目那不是单页?

  1. Is RequireJS even practical for projects that are not single-page?

在不使用优化器的情况下,我的每个主文件都以相同的配置选项开头:

Without using the optimizer, each of my main files start with essentially the same config options:

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 */ });

有没有办法避免这种情况?比如让每个主文件包含相同的构建配置文件而不必实际构建它?

Is there a way to avoid this? Like having each main file include the same build profile without having to actually build it?

r.js应该进入 httpdocs_siteroot 的父目录?

Should r.js go in httpdocs_siteroot's parent directory?

我的app dir结构或使用RequireJS有什么明显的错误吗?

Is there something glaringly wrong with my app dir structure or my use of RequireJS?


推荐答案

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

First of all, this is not a question with a unique solution. I'll explain the way I use RequireJS that works for me, and may work for you :)

其次,英语不是我的母语。有关该语言的更正和提示将非常感激。感觉自由,伙计们:)

Second, English is not my mother language. Corrections and tips about the language will be very appreciated. Feel free, guys :)


1)对于不是单页的项目,是否需要js实用?

1) Is require js even practical for projects that are not single-page?

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

It depends. If your project does not have shared code between pages for example, RequireJS help will be modest. The main idea of RequireJS is modularize the application into chunks of reusable code. If your application uses only page-specific code, then using RequireJS may not be a good idea.


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

2) Without using the optimizer, each of my main files start with essentially the same config options. Is there a way to avoid this? Like having each main file include the same build profile without having to actually build it?

我看到的唯一方法是进行配置主文件,或者创建一个将配置RequireJS的模块,然后将该模块用作main.js的第一个依赖项。但这可能很棘手。我的应用程序中没有使用很多main.js文件;我只使用一个作为加载器(见下文)。

The only way I see is making the configuration on the main file, or create a module that will configure RequireJS and then use that module as the first dependency on main.js. But this can be tricky. I do not use many main.js files in my applications; I use only one that acts as a loader (see below).


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

3) Should r.js go in httpdocs_siteroot's parent directory?

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

Not necessarily. You can put it inside the /media directory, since all your client stuff is there.


4)我的应用程序是否存在明显错误dir结构或我对requirejs的使用?

4) Is there something glaringly wrong with my app dir structure or my use of requirejs?

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

I would not say that. On the other hand, the structure is perhaps a bit too fragmented. For example, you can put all '3rd party stuff' inside a /vendor directory. But this is just sugar; your structure will work well and seems right. I think the major problem is the requirejs.config() call in multiple main files.

我遇到了同样的问题,我最终得到了以下解决方案:

I had the same problems you are having now and I ended up with the following solution:

1)不要使用define包装非AMD兼容文件。尽管它有效,但您可以使用requirejs.config中的shim属性获得相同的结果(见下文)。

1) Do not wrap the non-AMD-compliant files with a define. Although it works, you can achieve the same results using the "shim" property in requirejs.config (see below).

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

2) In a multi-page application, the solution for me is not to require the page-specific modules from the optimized main.js file. Instead, I require all the shared code (3rd party and my own) from the main file, leaving the page-specific code to load on each page. The main file ends up only being a loader that starts the page-specific code after loading all shared/lib files.

这是我用来构建的样板带有requirejs的多页面应用程序

目录结构:

/ src - 我把所有客户端内容在src目录中,所以我可以在这个目录中运行优化器(这是你的媒体目录)。

/src - I put all the client stuff inside a src directory, so I can run the optimizer inside this directory (this is your media directory).

/ src / vendor - 这里我放置所有第3个派对文件和插件,包括require.js。

/src/vendor - Here I place all 3rd party files and plugins, including require.js.

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

/src/lib - Here I place all my own code that is shared by the entire application or by some pages. In other words, modules that are not page-specific.

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

/src/page-module-xx - And then, I create one directory for each page that I have. This is not a strict rule.

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

/src/main.js: This is the only main file for the entire application. It will:


  • 配置RequireJS,包括垫片

  • 加载共享库/模块

  • 加载特定于页面的主模块

这是requirejs.config调用的示例:

This is an example of a requirejs.config call:

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()请求
库和之后请求我们的页面主模块。

And then, after configuration we can make the first require() request for all those libraries and after that do the request for our "page main" module.

//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 属性将保存当前页面的模块名称。

As you can see in the body of the require() above, we're expecting another attribute on the require.js script tag. The data-start attribute will hold the name of the module for the current page.

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

Thus, on the HTML page we must add this extra attribute:

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

通过这样做,我们将得到一个优化的main.js,其中包含 / vendor和/ lib目录(共享资源),但不是特定于页面的脚本/模块,因为它们不是作为依赖项在main.js中进行硬编码的。特定于页面的模块将在应用程序的每个页面上单独加载。

By doing this, we will end up with an optimized main.js that contains all the files in "/vendor" and "/lib" directories (the shared resources), but not the page-specific scripts/modules, as they are not hard-coded in the main.js as dependencies. The page-specific modules will be loaded separately on each page of the application.

页面主模块应返回函数()将由上面的app main执行。

The "page main" module should return a function() that will be executed by the "app main" above.

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

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

编辑

以下是如何使用构建配置文件来优化具有多个文件的页面特定模块的示例。

Here is example of how you can use build profile to optimize the page-specific modules that have more than one file.

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

For example, let's say we have the following page module:

/page1/main.js

/page1/main.js

/page1/dep1.js

/page1/dep1.js

/page1/dep2.js

/page1/dep2.js

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

If we do not optimize this module, then the browser will make 3 requests, one for each script. We can avoid this by instructing r.js to create a package and include these 3 files.

在构建配置文件的modules属性中:

On the "modules" attribute of the build profile:

...
"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模块中。
配置有点冗长,因为你必须为你有多个脚本文件的每个页面模块执行此操作。

By doing this, we create another per-page main file with all its dependencies. But, since we already have a main file that will load all our shared stuff, we don't need to include them again in page1/main module. The config is a little verbose since you have to do this for each page module where you have more than one script file.

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

I uploaded the code of the boilerplate in GitHub: https://github.com/mdezem/MultiPageAppBoilerplate. It is a working boilerplate, just install node and r.js module for node and execute build.cmd (inside the /build directory, otherwise it will fail because it uses relative paths)

我希望我已经清楚了。让我知道是否有些奇怪的事情;)

I hope I have been clear. Let me know if something sounds strange ;)

问候!

这篇关于如何在多页面项目中使用RequireJS构建配置文件+ r.js.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆