在页面之间重用Require.js shim配置

时间:2012-12-29 17:26:53

标签: requirejs

我有兴趣为我网站上的所有JavaScript代码创建一个配置对象。我找到了https://github.com/requirejs/example-multipage-shim,这是此设置的一个示例。

  

来自https://github.com/requirejs/example-multipage-shim(强调   我的):由于shim配置需要依赖项在页面中,   而不是使用data-main =“js / page1”作为page1.html,这个例子   在HTML页面中内联require调用。 如果使用了data-main   相反,然后'js / page1'没有任何内联依赖,   而且仍然依赖于'common'和'app / main1'构建层   持有模块,由于shim配置的限制   建立。

我不理解粗体句。这是否意味着“js / page1”如果存在则无法声明依赖关系?内联依赖是什么意思?内联到什么? HTML文件或JavaScript文件?

我阅读了有关shim config的API文档,但它对优化器的限制并不明确。

来自https://github.com/requirejs/example-multipage-shim/blob/master/www/page1.html

    <script src="js/lib/require.js"></script>
    <script>
        //Load common code that includes config, then load the app
        //logic for this page. Do the require calls here instead of
        //a separate file so after a build there are only 2 HTTP
        //requests instead of three.
        require(['./js/common'], function (common) {
            //js/common sets the baseUrl to be js/ so
            //can just ask for 'app/main1' here instead
            //of 'js/app/main1'
            require(['app/main1']);
        });
    </script> 

为什么以下错误?为什么“app / main1”必须与bootstrap(data-main)代码位于一个单独的模块中?

    <script src="js/lib/require.js"></script>
    <script>
        require(['js/common'], function (common) {
            var underscore = require('underscore');
            // ...
        });
    </script> 

3 个答案:

答案 0 :(得分:1)

我认为唯一可以避免重复你的垫片的真正解决方案可能是服务器端模板和像grunt.js这样的构建处理器的组合。

如果您想在优化的require.js加载和非优化模式之间切换(比如用于开发目的),您只需要服务器端模板部分。

  1. 定义一个包含共享填充程序的JavaScript文件。
  2. 如果使用grunt.js,请使用节点export语法导出填充程序和路径。
  3. 将它作为你的grunt配置的一部分。编写require.js配置文件或依赖 在grunt插件上,您可以轻松地重用require'ed 在内存中配置为require.js构建的一部分。
  4. 作为grunt构建的一部分,编写后端使用的服务器模板文件 建筑。例如,如果您使用的是django,请编写一个部分django模板 未检入存储库。可能包含.gitignore中的输出路径 如果您使用.git。
  5. 在index.html中或初始将partial作为全局变量加载到require.js之前 不使用优化填充程序时使用data-main的脚本标记。在requirejs电话中 使用从模板加载的数据将requirejs.config设置或扩展为
    的JavaScript。
  6. 一个不太理想但更简单的解决方案可能是简单地设置一个定义执行上下文的全局变量,然后加载一个共享条目requirejs脚本,然后在您的上下文变量上使用switch来调用require在运行时取决于上下文。这可能更难以优化。即使不那么优化,您也可以始终需要所有页面所需的所有内容,并使用此上下文来确定要运行的内容而不是需要的内容,但显然您总是加载所有JavaScript。这可能在浏览器扩展的上下文中起作用,尽管仍然可以通过处理所有不必要的JavaScript来减慢速度。

    说完这一切之后,如果requirejs提供了一种加载与requirejsdefine调用分开的配置的方法,那将是很好的,只是为了避免声明具有相同的填充程序的情况到处都是。

答案 1 :(得分:0)

最好在单独的javascript文件中定义(使用define)每个模块。否则,异步加载多个模块没有意义,因为它们位于相同的物理位置。在大多数情况下,您只需要使用函数define。只有在bootstrapping模块中,您才需要使用函数require。

当我使用require.js时,我有1个模块(bootstrap.js),它包含我的require.config对象和初始引导。在html页面中,您只需要包含1个脚本:require.js with bootstrap作为data-main属性值:

<强> HTML:

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

<强>自举:

require.config = {
   baseUrl: 'js',
   paths: {
     ...
   },
   shim: {
   }
   ...
};

// initial bootstrap
require(['jquery', 'angular', 'app'], function($, angular) {
   // do bootstrap
});

<强>模块:

define(['jquery'], function($) {
   // do sth with app
});

编辑:稍微误解了这个问题。

在使用data-main属性时,您无法在html页面中使用内联依赖项的原因是它可能无法加载它们。首先执行哪个代码块?数据主引导js还是内联代码?如果您的bootstrapping js文件将首先加载并将baseUrl设置为'js',则内联代码应使用require('common')而不是require('js/common')。但如果内联代码首先加载,则必须为require('js/common')

require('app/main1')在另一个需求块内的原因是相同的:模块'common'会将baseUrl更改为'js'。另外'app / main'可能需要来自'common'的一些shim配置。这是确保首先加载公共模块(使用shim配置)的唯一方法。

答案 2 :(得分:0)

当您使用 shim 配置时,为您希望异步加载的每个垫片添加匹配的路径配置属性:

requirejs.config({
    paths: {
        backbone: 'lib/backbone',
        jquery: 'lib/jquery',
        underscore: 'lib/underscore'
    },
    shim: {
        backbone: {
            deps: ['jquery', 'underscore'],
            exports: 'Backbone'
        },
        underscore: {
            exports: '_'
        },
        jquery: {
            exports: '$'
        }
    }
});

然后可以将垫片模块用作define()中的依赖项,就像任何其他实际模块一样。 (至少那是我的经历!)