Javascript 在上下文之间共享公共依赖关系 前提

Javascript 在上下文之间共享公共依赖关系 前提,javascript,requirejs,Javascript,Requirejs,假设我有两个不同的基于AMD的AngularJS应用程序,每个应用程序都有自己的控制器、指令、服务等。每个应用程序都捆绑在自己的dist/{app name}.min.js中,并加载到同一HTML页面的标记中(这一切都是在CMS的上下文中进行的,CMS包含这些应用程序以及其他内容) 现在,这些应用程序最终共享了一些服务、指令和供应商库,如angular本身、moment、jQuery,等等,因此我为所有这些资源创建了另一个文件夹,它将在应用程序的js包之前添加到页面中: <script s

假设我有两个不同的基于AMD的AngularJS应用程序,每个应用程序都有自己的控制器、指令、服务等。每个应用程序都捆绑在自己的
dist/{app name}.min.js
中,并加载到同一HTML页面的
标记中(这一切都是在CMS的上下文中进行的,CMS包含这些应用程序以及其他内容)

现在,这些应用程序最终共享了一些服务、指令和供应商库,如
angular
本身、
moment
jQuery
,等等,因此我为所有这些资源创建了另一个文件夹,它将在应用程序的js包之前添加到页面中:

<script src="/some-path/dist/shared-resources.min.js"></script>
<script src="/some-path/dist/first-app.min.js"></script>
<script src="/some-path/dist/second-app.min.js"></script>
这是通用模块的
build.js
文件的示例

({
    baseUrl: 'src',
    removeCombined: true,
    out: 'dist/shared-resources.min.js',
    paths: { // forcing a `common/{modulename}` convention
        'common/jquery': 'common/vendor/jquery.min',
        'common/moment': 'common/vendor/moment.min',
        'common/angular': 'common/vendor/angular/angular.min',
    },
    shim: {
        'common/angular': {
            exports: 'angular',
        }
    },
    include: [
        'common/modules/vendors', // Just a bundle of every vendor modules
        'common/directives/common-directive',
        'common/services/common-service'
    ],
})
现在我的意图是让所有共享模块都以
common/
命名,这样每个应用程序都可能需要
common/angular
common/directive/common directive
,等等,然后在创建包时排除
common
路径(因为所有公共模块都已经存在于
共享资源.js
包中),例如:

// first-app/src/first-app/controllers/app-controller.js
define([
    'first-app/modules/controllers',
    'first-app/services/app-service',
    'common/services/common-service'
], function (controllers) {
    'use strict';

    controllers.controller('AppController', ['CommonService', 'AppService', function (CommonService, AppService) {
        CommonService.call();
        AppService.call();
    }]);
});

// first-app/build.js
({
    baseUrl: 'src',
    out: 'dist/first-app.min.js',
    paths: {
        'common': 'empty:'
    },
    name: 'first-app',
    deps: ['first-app/app']
})
问题 问题在于,这两个应用程序(同样都加载在页面上)(这是不可避免的)应该如何正确查找这些通用模块

鉴于每个应用程序都有明显不同的
baseUrl
,它们被放在不同的RequireJS上下文中,否则第二个应用程序的
baseUrl
将覆盖第一个应用程序的
baseUrl
,导致其模块加载不正确:

// first-app/src/first-app.js
require.config({
    context: 'first-app',
    baseUrl: 'first-app/src',
})(['fist-app/app']);

// first-app/src/second-app.js
require.config({
    context: 'second-app',
    baseUrl: 'second-app/src',
})(['second-app/app']);
但是将它们放在上下文中会导致查找公共模块失败,因为这些模块是在上下文的
baseUrl
中查找的。实际上,这种情况只发生在第二个应用程序(按加载顺序排列的第二个应用程序),而页面中包含的第一个应用程序可以很好地加载公共模块

问题:
那么,我应该如何使应用程序正确地共享公共模块呢?我的做法是否有误?我应该使用除RequireJS之外的其他东西吗?

RequireJS的上下文功能实际上是用来处理一种情况,即您必须在同一页面上加载两个冲突的应用程序,否则冲突将无法解决迄今为止,您编写的代码可能导致您想要两个
baseUrl
值,但您的问题中没有任何内容表明您必须有两个
baseUrl
值。有几种方法可以避免:

  • 属于逻辑模块集一部分的模块应使用相对路径相互加载。例如,您给出的模块示例可以是:

    // first-app/src/first-app/controllers/app-controller.js
    define([
        '../modules/controllers',
        '../services/app-service',
        'common/services/common-service'
    ], function (controllers) {
    
  • 路径
    可以设置为使模块看起来像是直接位于
    baseUrl
    下,即使它不是。您可以:

    paths: {
        'first-app': 'first-app/src'
        'second-app': 'second-app/src'
    }
    
    是的,加载
    first-app/app
    会起作用。RequireJS会将路径转换为
    first-app/src/app.js

  • 谢谢,为路径定义一个“别名”就像一个符咒!
    paths: {
        'first-app': 'first-app/src'
        'second-app': 'second-app/src'
    }