共享上下文之间的公共依赖关系

时间:2015-11-16 09:31:45

标签: javascript requirejs

前提

假设我有两个不同的基于AMD的AngularJS应用程序,每个应用程序都有自己的控制器,指令,服务等等。每个应用程序都捆绑在自己的dist/{app-name}.min.js中并加载到{{1同一个HTML页面中的标签(这些都在CMS的上下文中,然后包含这些应用程序等)

现在应用程序最终共享了一些服务,指令和供应商库,如<script>本身,angularmoment等,所以我为所有人创建了另一个文件夹这些资源产生的捆绑包将在应用程序的js包之前添加到页面中:

jQuery

这是生成的文件夹结构:

<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>

这是常见模块的. ├── shared-resources/ │ ├── dist/ │ ├── src/ │ │ └── common/ │ │ ├── directives/ │ │ ├── modules/ │ │ ├── services/ │ │ └── vendor/ │ └── build.js │ ├── first-app │ ├── dist/ │ ├── src/ │ │ ├── first-app/ │ │ │ ├── controllers/ │ │ │ ├── modules/ │ │ │ ├── services/ │ │ │ ├── directives/ │ │ │ └── app.js │ │ └── first-app.js │ └── build.js │ └── second-app ├── dist/ ├── src/ │ ├── second-app/ │ │ ├── controllers/ │ │ ├── modules/ │ │ ├── services/ │ │ ├── vendor/ │ │ └── app.js │ └── second-app.js └── build.js 文件的示例

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等,然后排除{ {1}}创建捆绑包时的路径(因为所有常用模块已存在于common/directives/common-directive捆绑包中),例如:

common

问题

问题是如何在页面上加载 这两个应用程序(这是无法避免的),应该正确查找这些常用模块。

鉴于每个应用程序显然都有不同的shared-resources.js,它们会被置于不同的RequireJS上下文中,否则第二个应用程序的// 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 ,导致其模块加载错误:

baseUrl

但是将它们置于上下文中会导致查找公共模块失败,因为模块在上下文的baseUrl中查找。实际上这只发生在第二个应用程序(第二个按加载顺序),而第一个应用程序包含在页面中可以加载公共模块

问题

那么我应该如何让应用程序正确共享通用模块?我接近这个错吗?我应该使用除RequireJS之外的东西吗?

1 个答案:

答案 0 :(得分:0)

RequireJS的上下文功能实际上是用于处理必须在同一页面上加载两个冲突的应用程序的情况否则无法解决冲突。到目前为止您编写代码的方式可能导致您希望获得两个baseUrl值,但您的问题中没有任何内容表明您必须有两个baseUrl值。有办法避免它:

  1. 作为逻辑模块集的一部分的模块应该使用相对路径相互加载。例如,您提供的模块可以是:

    // first-app/src/first-app/controllers/app-controller.js
    define([
        '../modules/controllers',
        '../services/app-service',
        'common/services/common-service'
    ], function (controllers) {
    
  2. paths可以设置为外观,就像模块直接位于baseUrl下一样,即使它不是。你可以:

    paths: {
        'first-app': 'first-app/src'
        'second-app': 'second-app/src'
    }
    

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