Closed jeron-diovis closed 10 years ago
3-party модулем признаётся любой модуль, в конфиг которого добавлен exports, require или bind.
Добавляя, exports или require или bind, ты даешь понять, что данный модуль не совместим с CommonJS (иначе зачем все эти хаки?!) Всю ответственность за его зависимости берешь на себя. require() там оставлен для получения зависимостей, который ты написал в конфиге. exports и module не включается специально, чтобы не вводить в заблуждение модуль в любом случае он будет экспортироваться руками.
Ни Backbone ни Ember не умеют CommonJS или умеют очень криво. Я буквально вчера пытался подружить Ember c LMD - пришлось костылять. Вот примеры адаптации:
See 1
"backbone": {
"path": "lib/backbone/backbone.js",
"require": {
"underscore": "_",
"jQuery": "$"
},
"exports": "Backbone"
}
See 2
"ember": {
"path": "../bower_components/ember/ember.js",
"require": {
"jQuery": "jquery",
"Handlebars": "handlebars"
},
"exports": "Ember"
}
Наличие в конфиге флага amd: true отнюдь не гарантирует применения соответствующей обёртки.
LMD сканирует контент модуля, если тот AMD, то подставляет этот патч. Те для не-AMD-модулей var define = require.define
не добавляется ибо нет смысла. Прим
не совместим с CommonJS
А раз несовместим, то ему место в глобалах? Логично, ок. Но.
LMD сканирует контент модуля, если тот AMD, то подставляет этот патч.
То есть если в модуле уже присутствует define? Или посложнее? То, что для не-AMD нет смысла - разумеется. Но проблема в сторонних модулях, предусматривающих разные окружения. Пусть хоть тот же backbone. Его ветка для amd-загрузки делает абсолютно всё необходимое:
if (typeof define === 'function' && define.amd) {
define(['underscore', 'jquery', 'exports'], function(_, $, exports) {
...
Но LMD не даёт ему доступа к define. Поэтому данная ветка не может быть использована, и приходится "брать ответственность на себя", как показано выше. Но зачем вся эта писанина руками, когда у нас уже есть всё необходимое, чтобы просто позволить модулю использовать все те удобства, которые он для нас предусмотрел?
Хотя не всё необходимое - свойства "amd" у LMD-шной define нет. Возможно, стоит добавить?
Кроме того, эта проблема масштабируется и на композитные модули ("jquery+plugins"). Они попадают внутрь той же обёртки с вырезанным exports и отсутствующим define, и их логика экспорта тоже меняется. И получается полный бардак. Попробуй, например, собрать композитный модуль backbone c вот этим плагином: https://github.com/rsskga/backbone.validation Для него тоже зависимости вручную прописывать? Какой же это multipath тогда?
Я вижу решение в том, чтобы:
var define = require.define;
. Это полностью решает описанную проблему, а "бессмысленные" define могут появиться только если программист сам этого захочет.
Здраво или нет?
Но LMD не даёт ему доступа к define.
AMD планировалось использовать для модулей приложения, те когда первый стейтмент define()
.
добавить свойство "amd" к define
Это можнонужно сделать.
сделать персональный флаг "amd" для отдельных модулей
Я когда-то хотел добавить type-хинт для модулей, чтобы ускорить сборку(LMD не будет сканировать их, чтобы определить тип).
Попробуй, например, собрать композитный модуль backbone c вот этим плагином: https://github.com/rsskga/backbone.validation Для него тоже зависимости вручную прописывать? Какой же это multipath тогда?
"backbone": {
"path": ["lib/backbone/backbone.js", "lib/backbone/backbone.validation.js"],
"require": {
"underscore": "_",
"jQuery": "$"
},
"exports": "Backbone"
}
Вот так в теории должно работать.
Итого:
Все так?
Вот так в теории должно работать
Да, так работает. Пример я не очень выбрал)
Все так?
Всё так. Один уточняющий вопрос: за что будет отвечать type: "commonjs" - за наличие exports в обёртке?
Один уточняющий вопрос
LMD определяет тип модуля по контенту, но если добавить typе
, то он проигнорирует этот этап и возьмет тип из type
даже если он будет не верный.
Закрываю этот таск. См #183 #184
Fixed in lmd@1.13.1
Добрый день. Мне непонятны некоторые тонкости в обёртывании модулей.
wrap3partyModule
3-party модулем признаётся любой модуль, в конфиг которого добавлен exports, require или bind. При этом заголовок такого модуля устанавливается в '(function (require) {'. В результате этого, отсутствие exports радикально меняет внутреннюю логику экспорта такого модуля, полагающегося на традиционное "if (typeof exports !== 'undefined') {" - а это влечёт необходимость подстраивать конфиг уже под новое поведение.
Пример. Backbone, загружаемый как amd-модуль (он это умеет с v1.1), сам требует underscore и jquery. Загружаемый как commonjs-модуль, jquery он уже не требует (не знаю, зачем они так сделали, но как есть). Допустим, я использую commonjs, но при этом хочу, чтобы он всё же использовал именно jquery. Дописываю "require: 'jquery'" -> модуль становится 3-party -> exports из обёртки выбрасывается -> заголовок backbone решает, что у нас нет ни amd, ни commonjs -> backbone экспортируется вообще в глобалы, при этом ещё и underscore перестаёт сам запрашивать -> приходится дописывать в require ещё и underscore.
Думается, это отнюдь не прозрачное и логичное поведение.
Собственно, вопрос - почему exports и module не включаются в обёртку для 3-party модулей (чем негативным это может грозить)? Можно ли их добавить?
wrapAmdModule
Наличие в конфиге флага amd: true отнюдь не гарантирует применения соответствующей обёртки. Да, в сборку добавляется плагин с функцией define, но в самих модулях после сборки "var define = require.define" отсутствует - что, опять же, меняет логику экспортирования этих модулей, и они грузятся отнюдь не как amd. Так и должно быть, или что-то здесь не так?