Comments 46
А чем не устроили require.js? В чем преимущества вашего решения?
смысл использовать его только для сборки?
browserify — отлиная штука, мне она очень нравится, но для работы собранного кода она добавляет реализацию дополнительных функций вроде define, а я хочу получать чистый код
Каких функций? Там обертка не намного больше чем у вас получается.
Возьмём три простых модуля и сравним.
Definer.
Модули:
Собранный файл (206 символов):
Browserify.
Модули:
Собранный файл (828 символов):
Очевидно, файл, собранный с помощью definer работает быстрее и его проще отлаживать.
Definer.
Модули:
definer('a', function() { return 'a'; });
definer('b', function() { return 'b'; });
definer('c', function(a, b) { return a + b + 'c'; });
Собранный файл (206 символов):
(function(global, undefined) {
var a = (function () { return 'a'; }).call(global),
b = (function () { return 'b'; }).call(global),
c = (function (a, b) { return a + b + 'c'; }).call(global, a, b);
})(this);
Browserify.
Модули:
module.exports = function() { return 'a'; };
module.exports = function() { return 'b'; };
module.exports = function() { return require('./a') + require('./b') + 'c'; }
Собранный файл (828 символов):
require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
module.exports = function() { return 'a'; };
},{}],2:[function(require,module,exports){
module.exports = function() { return 'b'; };
},{}],"XGSqeA":[function(require,module,exports){
module.exports = function() { return require('./a') + require('./b') + 'c'; }
},{"./a":1,"./b":2}],"./c.js":[function(require,module,exports){
module.exports=require('XGSqeA');
},{}]},{},[])
Очевидно, файл, собранный с помощью definer работает быстрее и его проще отлаживать.
Да вы не заметите разницу на нормальном приложении, а не на синтетическом примере. То о чем вы говорите — микрооптимизация.
Definer предназначается в первую очередь для разработки библиотек и инструментов для разработчиков.
Когда вы предоставляете другому разработчику библиотеку, важно, чтобы там не было ничего лишнего, а вырезать куски кода регулярными выражениями, как это делает jQuery мне кажется дикостью.
Когда вы предоставляете другому разработчику библиотеку, важно, чтобы там не было ничего лишнего, а вырезать куски кода регулярными выражениями, как это делает jQuery мне кажется дикостью.
> Когда вы предоставляете другому разработчику библиотеку, важно, чтобы там не было ничего лишнего
Чтобы не было ничего лишнего для пользователя библиотеки (в том числе лишнего функционала), важно чтобы библиотека сама была в виде набора модулей в стандартном формате. Чтобы пользователь библиотеки мог использовать только то, что ему нужно.
Ради примера — посмотрите на библиотеки на npm, например на React, он поставляется в ввиде набора CommonJS модулей, которые потом можно собрать в вместе с приложением с помощью browserify, webpack или чем-нибудь другим.
Чтобы не было ничего лишнего для пользователя библиотеки (в том числе лишнего функционала), важно чтобы библиотека сама была в виде набора модулей в стандартном формате. Чтобы пользователь библиотеки мог использовать только то, что ему нужно.
Ради примера — посмотрите на библиотеки на npm, например на React, он поставляется в ввиде набора CommonJS модулей, которые потом можно собрать в вместе с приложением с помощью browserify, webpack или чем-нибудь другим.
Думаю, что подавляющее большинство разработчиков не собирает библиотеки по частям, а просто скачивают собранный файл в один клик.
Но если хочется кастомно собрать проект из необходимых модулей, то с помощью definer можно сделать и это. А какую команду для сборки вы будете использовать, уже не так важно, хоть grunt, хоть make, или npm run-script и так далее.
Но если хочется кастомно собрать проект из необходимых модулей, то с помощью definer можно сделать и это. А какую команду для сборки вы будете использовать, уже не так важно, хоть grunt, хоть make, или npm run-script и так далее.
Думаю подавляющее большинство разработчиков не будет беспокоится из-за лишних 500 байт. Но если уж кто-то и будет, то точно пойдет по пути использования модульных библиотек, где модно сэкономить гораздо больше.
Здесь дело не в том, grunt, make или npm run-script, а в том, какая система модулей используется (синтаксис и семантика).
Здесь дело не в том, grunt, make или npm run-script, а в том, какая система модулей используется (синтаксис и семантика).
Какая вам разница, какая система модулей используется в проекте, если вы можете собрать необходимый модуль командой
Спросите у разработчиков jQuery, зачем они вырезают из собранного файла всё про RequireJS.
make modulename
?Спросите у разработчиков jQuery, зачем они вырезают из собранного файла всё про RequireJS.
То есть для каждого модуля библиотеки мне надо будет делать
make modulename
? Спасибо, я лучше browserify/webmake попользуюсь.Это же абстрактный пример. К тому же использование browserify сводится к тому же самому.
Сборка указанного модуля приведёт к получению файла, содержащего все модули, необходимые для его работы. Если надо собрать несколько модулей, то можно
Сборка указанного модуля приведёт к получению файла, содержащего все модули, необходимые для его работы. Если надо собрать несколько модулей, то можно
make module1 module2 ... moduleN
.jQuery кстати есть на npm, жаль что там не модуляризованный билд… Но вот например lodash —
var assign = require('lodash/compat/objects/assign')
если нужна всего одна функция.После gzip, разница всего в 200 байт, кстати. Но это ещё не все — у webpack overhead ещё меньше.
Смысл не в байтах, а в читаемости финального кода и максимальной приближенности к оригиналу.
> Смысл не в байтах, а в читаемости финального кода и максимальной приближенности к оригиналу.
С source maps (которые кстати генерирует browserify) вы это все получаете в полном объеме — при ошибке будут видны строки оригинального файла и при клике в devtools вам покажутся оригинальные исходники.
Видимо вы не пробовали пользоваться browserify/webmake/…
С source maps (которые кстати генерирует browserify) вы это все получаете в полном объеме — при ошибке будут видны строки оригинального файла и при клике в devtools вам покажутся оригинальные исходники.
Видимо вы не пробовали пользоваться browserify/webmake/…
У разработчика, использующего скачанную библиотеку нет оригинальных исходников.
source map обычно идет вместе с собранной и минифицированной версией библиотеки. И нормальный разработчик вообще ничего скачивать не будет руками, а возьмет bower.
Суть в чем, у вас своя система модулей, несмотря на то что существуют популярные форматы вроде common.js. require.js и т.д. Причем я бы даже модулями это не назвал, есть для grunt кучи плагинов которые в нужное место подставляют запрошенный код, оверхэда вообще нету, и результат будет приблизительно таким же.
Суть в чем, у вас своя система модулей, несмотря на то что существуют популярные форматы вроде common.js. require.js и т.д. Причем я бы даже модулями это не назвал, есть для grunt кучи плагинов которые в нужное место подставляют запрошенный код, оверхэда вообще нету, и результат будет приблизительно таким же.
Ещё раз, если вы используете browserify/webpack/…
- вы не скачиваете билд библиотеки, вы устанавливаете пакет из npm/bower/github/....
- в пакете — оригинальные исходники ввиде отдельных модулей
- вы собираете свое приложение, которое использует библиотеки (сборщик узнает об этом анализирую
require()
вызовы) - на выходе имеет билд своего приложение + source map (внутри сам source map + оригинальные исходники, можно настроить это отдельно, чтобы исходники подгружались по необходимости)
require.js не нравится тем, что после сборки требуются дополнительные функции для работы кода, а вырезать их, как это делает jQuery — не хочется: github.com/jquery/jquery/blob/master/build/tasks/build.js
Кажется, определение зависимостей не переживет сжатие кода.
очень похоже на то
В Angular же справляются как-то с этой проблемой:)
Ну там у injectable должен быть прописан список того, что нужно инджектить. Он покоится в свойстве .$inject вроде как, как массив названий сервисов. При объявлении injectable можно либо самому указать, либо прописать через array notation (типа обернуть в массив, где определение нашего сервиса будет последним элементом, а до этого названия сервисов) либо ангулар сам возьмет из названий аргументов.
Переживёт, ведь собранный файл представляет из себя чистый код вроде такого:
(function(global, undefined) {
var a = (function () { return 'a'; }).call(global),
b = (function () { return 'b'; }).call(global),
c = (function (a, b) { return a + b + 'c'; }).call(global, a, b);
})(this);
Самая простая модульная система
Извините, а чем она проще в использовании чем requirejs?
Github-проект на русском — это очень печально.
Согласен, но мой английский пока не позволяет нормально писать.
Если пришлёте пулреквест с документацией на английском — буду сильно благодарен :)
Если пришлёте пулреквест с документацией на английском — буду сильно благодарен :)
У сабжа есть ряд недостатков, из-за которых я не стану им пользоваться и, следовательно, участвовать.
1) > Модули должны быть объявлены в правильной последовательности, иначе возникнет ошибка.
То есть сабж не помогает разрешать зависимости.
2) Сабж не автоматизирует подключение модулей в качестве отдельных <script>'ов в девелопменте и единственного минифицированного файла в продакшене.
Честно говоря, непонятно, зачем он вообще нужен.
1) > Модули должны быть объявлены в правильной последовательности, иначе возникнет ошибка.
То есть сабж не помогает разрешать зависимости.
2) Сабж не автоматизирует подключение модулей в качестве отдельных <script>'ов в девелопменте и единственного минифицированного файла в продакшене.
Честно говоря, непонятно, зачем он вообще нужен.
1) Эта ошибка описана для ясности, в жизни же не предполагается такое использование системы, а зависимости нормально разрешаются при сборке.
2) В девелопменте с помощью грант-плагина можно автоматизировать сборку и добавить минификацию с помощью grunt-contrib-uglify, например.
Мне definer нужен в первую очередь для того, чтобы писать инструменты с разбивкой по модулям и автоматически собирать единый файл без модулей, который легко сможет использовать кто-то другой.
2) В девелопменте с помощью грант-плагина можно автоматизировать сборку и добавить минификацию с помощью grunt-contrib-uglify, например.
Мне definer нужен в первую очередь для того, чтобы писать инструменты с разбивкой по модулям и автоматически собирать единый файл без модулей, который легко сможет использовать кто-то другой.
Я использую Sprockets. Он работает так:
Я перечисляю для Sprockets имена неминифированных файлов модулей. При этом разрешение зависимостей лежит на моих плечах: я должен позаботиться, чтобы зависимости были объявлены раньше зависимых модулей.
Если я запускаю проект в девелопменте, то в HTML каждый модуль появляется в виде отдельного неминифицироавнного файла.
Если в продакшене, то в HTML появляется один минифицированный и конкатенированный файл.
Никаких сборок типа `grunt build` я при этом не запускаю.
Definer мне может как-то помочь?
Я перечисляю для Sprockets имена неминифированных файлов модулей. При этом разрешение зависимостей лежит на моих плечах: я должен позаботиться, чтобы зависимости были объявлены раньше зависимых модулей.
Если я запускаю проект в девелопменте, то в HTML каждый модуль появляется в виде отдельного неминифицироавнного файла.
Если в продакшене, то в HTML появляется один минифицированный и конкатенированный файл.
Никаких сборок типа `grunt build` я при этом не запускаю.
Definer мне может как-то помочь?
По моему модули, в итоге все же присутствуют. Отсутствуют файлы модулей, но сами модули, как объекты, обернутые анонимной функцией, присутствуют в конечном файле.
Sign up to leave a comment.
Definer.js — простая модульная система