4

(这与使用 dojo 构建系统的 wirejs 和 dojo相同,但有更多关于问题的详细信息和尝试过的解决方案。创建了重复的问题,因为这是在评论中提出的)。

在构建使用wire 的dojo 应用程序时,dojo 加载程序会undefinedModule为“./lib/context”抛出一个我们无法摆脱的错误。

wire使用 git 子模块添加到一个大型的、正在工作的 dojo 项目中。事实证明,cujojswhen和 cujojsmeld也是必需的。我也将它们添加为 git 子模块。

在这个项目中,库不在应用程序文件夹 ( src/app) 旁边,而是在src/lib. 所以我有src/lib/wire, src/lib/when, , src/lib/meldnext tosrc/lib/dgrid等。dojo库有 2 层深:src/lib/dojo/dojo,src/lib/dojo/dijit和.src/lib/dojo/dojoxsrc/lib/dojo/util

版本:

  • 道场 1.10.4
  • 电线 0.10.9
  • 当 3.7.2
  • 融合 1.3.1

一旦我将以下包定义添加到dojoConfig

var dojoConfig = (function() {

  [...]

  return {

    [...]

    packages: [

      [...]

      {name: "wire", location: "../../wire", main: "wire"},
      {name: "when", location: "../../when", main: "when" },
      {name: "meld", location: "../../meld", main: "meld" },

      [...]

    ],

    [...]
  };

})();

请注意,有必要添加main条目。例如,这使得在依赖项列表中引用when/when.jsas成为可能,而不是cujojs 代码在内部执行的操作。"when""when/when"

因此,这在开发模式下有效。

接下来,我试图让构建工作。

在 中build.profile.js,我再次添加了包引用。构建以多种方式失败。

首先,对于包,dojo 构建器期望文件中有一个dojoBuild属性package.json,它引用一个<mypackage>.profile.jspackage.js文件,它本质上定义了包的构建配置。这个构建配置通常(它在我们所有的包中)只是一个resourceTags对象,其函数定义了包中的 AMD 资源文件、测试文件以及应按原样复制的文件。

cujojs 包没有可用于dojo 构建器的构建定义。

构建器首先抱怨这些包没有构建配置,其次资源没有被标记为 AMD 资源(这是构建配置文件的主要原因)。

由于我不想更改我使用的外部库的文件,因此我不倾向于向dojoBuildcujojs 包添加属性和构建配置文件,因此我寻求解决方法。

单步执行dojo builder代码后,发现builder报错package.json文件没有dojoBuild属性,最后只看内部包定义结构获取resourceTags对象。内部包定义结构从主构建配置文件中的包定义开始。所以,我最终在那里捎带了一个resourceTags对象:

[...]

/*
 wire, when and meld don't have a good build profile set up.
 Here, we doctor a resourceTags (i.e., the core of a build profile). We set it on the package definition.
 This is an unsupported hack. The builder will still complain about there not being a build profile, but
 it will use these definitions when building those packages.

 Note: // see https://github.com/cujojs/when/wiki/Using-with-Dojo does not work!
*/
var generalResourceTags = (function () {

  function isTest(filename, mid) {
    return filename.indexOf("test/") >= 0;
  }

  function isCopyOnly(filename, mid) {
    return filename.indexOf(".html") >= 0;
  }

  function isAmd(filename, mid) {
    return filename.indexOf(".json") < 0 && filename.indexOf(".js") >= 0 && filename.indexOf(".profile.js") < 0;
  }

  function isGivingTroubleButUnused(filename, mid) {
    return /^wire\/jquery\//.test(mid) ||
           mid === "wire/sizzle" ||
           /^when\/build\//.test(mid) ||
           /^when\/es6-shim\//.test(mid) ||
           mid === "when/generator"; // see https://github.com/cujojs/when/issues/429
  }

  return {
    test: function (filename, mid) {
      return isTest(filename, mid);
    },

    copyOnly: function (filename, mid) {
      return isCopyOnly(filename, mid) || isGivingTroubleButUnused(filename, mid);
    },

    amd: function (filename, mid) {
      return !isTest(filename, mid) && !isCopyOnly(filename, mid) && isAmd(filename, mid) && !isGivingTroubleButUnused(filename, mid);
    }
  }
})();

var profile = {
  releaseName: releaseName,
  releaseDir: "../../../../release",
  action: 'release',
  cssOptimize: 'comments',
  mini: true,
  optimize: 'closure',
  layerOptimize: 'closure',
  stripConsole: 'normal',
  selectorEngine: 'acme',
  useSourceMaps: false,

  [...]  

  packages: [

    [...]

    {name: "wire", location: "../../wire", main: "wire", destLocation: "./lib/wire", resourceTags: generalResourceTags},
    {name: "when", location: "../../when", main: "when", destLocation: "./lib/when", resourceTags: generalResourceTags},
    {name: "meld", location: "../../meld", main: "meld", destLocation: "./lib/meld", resourceTags: generalResourceTags},

    [...]

  ],
  layers: {

    [...]

  },
  staticHasFeatures: {
    "config-publishRequireResult": false,
    "dijit-legacy-requires": false,
    "dojo-debug-messages": false,
    "dojo-firebug": false,
    "dojo-log-api": 0,
    "dojo-mobile-parser": false,
    "dojo-moduleUrl": false,
    "dojo-parser": true,
    "dojo-publish-privates": 0,
    "dojo-test-sniff": 0,
    "dojo-trace-api": 0,
    "dom-addeventlistener": true,
    "extend-dojo": true,
    "host-browser": true,
    "mvc-bindings-log-api": false,

    [...]

  }
};

请注意和resourceTags的包定义中wire的额外属性。我保持“简单”,只使用一个通用对象来处理所有 3 种情况,. 这是一个非常标准的设置,除了,我稍后会介绍。whenmeldgeneralResourceTagsresourceTagsisGivingTroubleButUnused

请注意,我尝试了在https://github.com/cujojs/when/wiki/Using-with-Dojo for中明确提到的解决方案when,但它不起作用

这样,我们从 dojo builder 那里得到了一份相当不错的报告,但它提到了一些缺失的资源。例如,某些模块需要 jquery。但是,这些模块没有在这个项目中使用。

请注意,wirejs 和 dojo 中提到的解决方案使用 dojo 构建系统,捎带packageJson可能会更好。我没有测试过。

我最终引入了isGivingTroubleButUnused复制这些模块而不处理它们,因为我们无论如何都不使用它们。请注意,其中 1 个问题在when/generator. Closure 编译器在此处看到语法错误(请参阅https://github.com/cujojs/when/issues/429)。

此设置的最终结果是构建没有错误。

然后,我们想对此进行测试……但它失败了。我们得到的第一个错误确实是 dojo 加载程序抛出了一个undefinedModule Errorfor "./lib/context"。这确实发生在第 23 行的唯一位置wire/wire.js

createContext = require('./lib/context');

这是为了解决wire/lib/context.js,显然这在开发(取消构建)模式下有效。

在任何情况下,require它都旨在成为上下文相关的要求(参见 dojotoolkit.org /documentation/tutorials/1.10/modules_advanced/,“有条件地要求模块”),因为模块引用是相对的。但这不应该是它无法构建且无法构建的原因。

接下来,我尝试只复制所有wire,whenmeld资源。如果资源不包含在层的 dojo 构建中,它只会退回到异步加载。所以,这可以工作:

var generalResourceTags = (function () {

  function isTest(filename, mid) {
    return filename.indexOf("test/") >= 0;
  }

  [...]

  return {
    test: function (filename, mid) {
      return isTest(filename, mid);
    },

    copyOnly: function (filename, mid) {
      return !isTest(filename, mid);
    },

    amd: function (filename, mid) {
      return false;
    }
  }
})();

构建现在通过,并复制所需的内容。当然,还有更多错误,应用程序代码引用的地方wire,但这是意料之中的(error(311) Missing dependency. module: MY_MODULE; dependency: wire!SOME_PACKAGE/_wire-serverRequests)。

然而,浏览器在同一个地方给出了同样的错误:一个undefinedModule Errorfor "./lib/context"

此时的工作假设是wire,名称下使用的函数require在构建版本中不是上下文敏感的需求,而是在未构建版本中。

这不是真的。首先,我更改了wire代码或测试以阅读

createContext = require('wire/lib/context');

使参考绝对。同样的问题。

然后,我尝试使用 sourceMaps ( useSourceMaps = true) 进行调试。这是一场噩梦,但我相信我看到require使用的是相同的,上下文相关的要求。

也许“预加载”有效?因此,在顶部的 HTML 页面中,我将所有代码都用

require(["wire/lib/context"], function() {

  [...]

});

这确保context在我们做任何其他事情之前加载。同样的错误。

接下来,我在代码中添加了日志记录wire/lib/context

console.error("Defining context");

var when, mixin, loaderAdapter, relativeLoader, Container, specUtils;

when = require('when');
console.error("Loaded when");
mixin = require('./object').mixin;
console.error("Loaded ./object");
loaderAdapter = require('./loader/adapter');
console.error("Loaded ./loader/adapter");
relativeLoader = require('./loader/relative');
console.error("Loaded ./loader/relative");
Container = require('./Container');
console.error("Loaded ./Container");
specUtils = require('./specUtils');

console.error("Defined context. Returning.");

(使用error, 因为其他消息在构建中被剥离)。

在 unbuild 版本中,我看到所有消息。在构建版本中,我在错误发生之前只看到“定义上下文”。所以问题不在于“加载” wire/lib/context,而在于定义它,并且可能在于加载或定义when

所以,我申请了同样的技巧when

console.error("Defining when");

var timed = require('./lib/decorators/timed');
console.error("Loaded lib/decorators/timed");
var array = require('./lib/decorators/array');
console.error("Loaded lib/decorators/array");
var flow = require('./lib/decorators/flow');
console.error("Loaded lib/decorators/flow");
var fold = require('./lib/decorators/fold');
console.error("Loaded lib/decorators/fold");
var inspect = require('./lib/decorators/inspect');
console.error("Loaded lib/decorators/inspect");
var generate = require('./lib/decorators/iterate');
console.error("Loaded lib/decorators/iterate");
var progress = require('./lib/decorators/progress');
console.error("Loaded lib/decorators/progress");
var withThis = require('./lib/decorators/with');
console.error("Loaded lib/decorators/with");
var unhandledRejection = require('./lib/decorators/unhandledRejection');
console.error("Loaded lib/decorators/unhandledRejection");
var TimeoutError = require('./lib/TimeoutError');
console.error("Loaded lib/TimeoutError");
[...]

现在unbuild版本有一个惊喜。输出是:

Defining when
Loaded lib/decorators/timed
Loaded lib/decorators/array
Loaded lib/decorators/flow
Loaded lib/decorators/fold
Loaded lib/decorators/inspect
Loaded lib/decorators/iterate
Loaded lib/decorators/progress
Loaded lib/decorators/with
Loaded lib/decorators/unhandledRejection
Loaded lib/TimeoutError
Loaded lib/Promise
Loaded lib/apply
Defined when
Defining context
Loaded when
Loaded ./object
Loaded ./loader/adapter
Loaded ./loader/relative
Loaded ./Container
Defined context. Returning.

这意味着when定义在定义之前 context开始。这很奇怪,因为我没有看到任何代码可以告诉加载器whencontext, 之前的行

when = require('when');

在“定义上下文”的记录之后执行。

在构建版本中,我们仍然只得到

Defining context

在错误发生之前!这种行为明显不同!

接下来,我删除了预加载代码。取消构建代码给出相同的输出,构建代码现在在错误发生之前没有消息。

所以无论如何,这段wire代码在加载过程中做着我不期望和不理解的事情。

我确实希望这个额外的细节会触发某人让我们走上正确的轨道......

4

0 回答 0