wirejs и dojo, использующие систему сборки dojo (2)

(Это тот же вопрос, что и для wirejs и dojo, использующих систему сборки dojo, но с более подробной информацией о проблеме и пробных решениях. Повторяющийся вопрос создан, потому что это было предложено в комментарии).

При создании приложения dojo, которое использует провод, загрузчик dojo выдает undefinedModule Ошибка для "./lib/context", от которой мы не можем избавиться.

я добавил wire в большой, работающий проект dojo с использованием подмодуля git. Оказалось, что также cujojs when и cujojs meld являются обязательными. Я добавил их как подмодуль git тоже.

В этом проекте библиотеки не находятся рядом с папкой приложения (src/app), но на один уровень вглубь src/lib, Так что я src/lib/wire, src/lib/when, src/lib/meld, рядом с src/lib/dgrid, так далее. dojo библиотеки имеют 2 уровня глубины: src/lib/dojo/dojo, src/lib/dojo/dijit, src/lib/dojo/dojox а также src/lib/dojo/util,

Версии:

  • додзё 1.10.4
  • провод 0.10.9
  • когда 3.7.2
  • смесь 1.3.1

Вещи работают в разработке (unbuild), как только я добавлю следующие определения пакета в 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.js как раз "when" в списке зависимостей, а не "when/when", что код cujojs делает внутри.

Итак, это работает в режиме разработки.

Затем я попытался заставить сборку работать.

в build.profile.js Я снова добавил ссылки на пакеты. Сбой сборки таким образом несколькими способами.

Во-первых, для пакетов конструктор dojo ожидает dojoBuild недвижимость в package.json файлы, которые относятся к <mypackage>.profile.js или же package.js файл, который по существу определяет конфигурацию сборки для пакетов. Эта конфигурация сборки чаще всего (она есть во всех наших пакетах) просто resourceTags объект, с функциями, которые определяют, какие файлы являются ресурсами AMD в пакете, какие файлы являются тестами, а какие должны быть скопированы как есть.

Пакеты cujojs не имеют таких определений сборки, пригодных для сборки dojo.

Во-первых, разработчик жалуется на то, что для этих пакетов нет конфигурации сборки, а во-вторых, что ресурсы не помечаются как ресурсы AMD (что является основной причиной наличия файлов конфигурации этой сборки).

Поскольку я не хочу изменять файлы внешней библиотеки, которую я использую, я не склонен добавлять dojoBuild Свойство и файл конфигурации сборки для пакетов cujojs, поэтому я искал обходной путь.

Пройдя по коду сборки Dojo, я обнаружил, что сборщик жалуется на 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, when а также meld, Я держал вещи "простыми", и просто использовал один общий объект для обработки всех трех случаев, generalResourceTags, Это довольно стандарт resourceTags установка, кроме isGivingTroubleButUnused который я получу через мгновение.

Обратите внимание, что я попробовал упомянутое решение подробно на https://github.com/cujojs/when/wiki/Using-with-Dojo для when и что это не сработало.

Таким образом, мы получаем довольно приличный отчет от сборщика додзё, но в нем упоминаются некоторые недостающие ресурсы. Например, некоторые модули требуют jquery. Но эти модули не используются в этом проекте.

Обратите внимание, что решение, упомянутое в wirejs и dojo с использованием системы сборки dojo, piggy-backing packageJson может быть лучше. Я не проверял это.

Я закончил тем, что представил isGivingTroubleButUnused скопировать эти модули, не обращаясь с ними, так как мы их все равно не используем. Обратите внимание, что 1 из проблем находится в when/generator, Компилятор Closure видит там синтаксическую ошибку (см. https://github.com/cujojs/when/issues/429).

Конечным результатом этой настройки является сборка без ошибок.

И затем, мы хотим проверить это... и это не удается. Первая ошибка, которую мы получаем, это загрузчик dojo undefinedModuleError за "./lib/context", Единственное место, где это происходит, действительно на линии 23 wire/wire.js:

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

Это предназначено для разрешения wire/lib/context.jsи, очевидно, это работает в режиме разработки (unbuild).

В любом случае, require предполагается, что это контекстно-зависимая потребность (см. dojotoolkit.org /documentation/tutorials/1.10/modules_advanced/, "Условно требующие модули"), поскольку ссылка на модуль является относительной. Но это не должно быть причиной, почему он работает без сборки и не работает с сборкой.

Затем я попытался скопировать все wire, when а также meld Ресурсы. Если ресурс не включен в сборку слоя 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).

Тем не менее, браузер выдает ту же ошибку, в том же месте: undefinedModuleError за "./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 определение. Это странно, потому что я не вижу кода, который мог бы сказать загрузчику, что when требуется в context перед линией

when = require('when');

выполняется после регистрации "Определение контекста".

В сборочной версии мы все еще получаем

Defining context

до появления ошибки! Это поведение явно отличается!

Далее я удалил код предварительной загрузки. Код Unbuild дает тот же вывод, код сборки теперь не имеет сообщений до возникновения ошибки.

Так что в любом случае это wire код делает вещи, которые я не ожидаю и не понимаю во время загрузки.

Я очень надеюсь, что эта дополнительная деталь побудит кого-то направить нас на правильный путь...

0 ответов

Другие вопросы по тегам