Нужен стиль в JavaScript-браузере?
Существуют ли библиотеки для браузера в браузере, которые обеспечивают такую же гибкость/модульность/простоту использования, как require
узла?
Для того, чтобы предоставить более подробную информацию: причина require
настолько хороша, что она:
- Позволяет динамически загружать код из других мест (что, на мой взгляд, стилистически лучше, чем связывание всего кода в HTML)
- Он обеспечивает согласованный интерфейс для построения модулей
- Модулям легко зависеть от других модулей (поэтому я мог бы написать, например, API, который требует jQuery, поэтому я могу использовать
jQuery.ajax()
- Загруженный javascript имеет область видимости, то есть я могу загрузить с помощью
var dsp = require("dsp.js");
и я смог бы получить доступ к dsp.FFT
, что не помешало бы моему локальному var FFT
Мне еще предстоит найти библиотеку, которая делает это эффективно. Обходные пути, которые я имею в виду:
-
coffeescript-concat - достаточно просто потребовать другие js, но вы должны скомпилировать его, что означает, что он менее велик для быстрой разработки (например, создание API-интерфейсов в тесте)
-
RequireJS - он популярен, прост и решается 1-3, но отсутствие обзора - это реальный развязка (я считаю, что head.js похож на то, что ему не хватает обзора, хотя у меня никогда не было возможности его использовать. Точно так же LABjs может загружаться, а .wait()
проблемы с зависимостями, но по-прежнему не делает видимости)
Насколько я могу судить, существует множество решений для динамической и/или асинхронной загрузки javascript, но они, как правило, имеют те же проблемы, что и при загрузке js из HTML. Больше всего на свете я хотел бы загрузить javascript, который вообще не загрязняет глобальное пространство имен, но все же позволяет мне загружать и использовать библиотеки (так же, как это требует узел).
EDIT (MY ANSWER): С момента написания этого, я широко использовал RequireJS (который теперь имеет гораздо более четкую документацию). Требование действительно было правильным выбором, на мой взгляд. Я хотел бы уточнить, как система работает для людей, которые так же запутались, как и я:
Вы можете использовать require
в повседневной жизни. Модуль может быть любым, возвращаемым функцией (как правило, объектом или функцией) и определяется как параметр. Вы также можете скомпилировать свой проект в один файл для развертывания с использованием r.js
(на практике это почти всегда быстрее, хотя require
r.js
скриптов).
Основное различие между RequireJS и node-style требует, например, браузера (классный проект, предложенный tjameson), так это то, как модули разрабатываются и требуются:
- RequireJS использует AMD (определение модуля Async). В AMD
require
получить список модулей (файлы javascript) для загрузки и функцию обратного вызова. Когда он загружает каждый из модулей, он вызывает обратный вызов с каждым модулем в качестве параметра для обратного вызова. Таким образом, он действительно асинхронен и поэтому хорошо подходит для Интернета. - Узел использует CommonJS. В CommonJS
require
блокирующий вызов, который загружает модуль и возвращает его как объект. Это отлично работает для узла, потому что файлы считываются с файловой системы, что достаточно быстро, но работает плохо в Интернете, потому что загрузка файлов синхронно может занять гораздо больше времени.
На практике многие разработчики использовали Node (и, следовательно, CommonJS), прежде чем они увидели AMD. Кроме того, многие библиотеки/модули написаны для CommonJS (путем добавления вещей к объекту exports
), а не для AMD (путем возврата модуля из функции define
). Поэтому многие разработчики, основанные на узлах, хотят использовать библиотеки CommonJS в Интернете. Это возможно, так как загрузка из <script>
блокируется. Такие решения, как браузер, используют модули CommonJS (Node) и завершают их, чтобы вы могли включать их с помощью тегов скриптов.
Поэтому, если вы разрабатываете свой собственный многофайловый проект для Интернета, я настоятельно рекомендую RequireJS, поскольку он действительно является модульной системой для Интернета (хотя при честном раскрытии я считаю AMD намного более естественным, чем CommonJS). В последнее время различие стало менее важным, так как RequireJS теперь позволяет существенно использовать синтаксис CommonJS. Кроме того, RequireJS можно использовать для загрузки модулей AMD в Node (хотя я предпочитаю node-amd-loader).
Ответы
Ответ 1
Заканчиваем. Он многое делает.
Кроме того, браузер очень хорош. Я использовал require-kiss, и он работает. Возможно, есть и другие.
Я не уверен в RequireJS. Это просто не то же самое, что и у узла. Вы можете столкнуться с проблемами при загрузке из других мест, но это может сработать. До тех пор, пока существует метод предоставления или что-то, что можно назвать.
TL; DR - я бы рекомендовал браузеру или потребовать поцелуй.
Обновить:
require-kiss теперь мертв, и автор удалил его. С тех пор я использовал RequireJS без проблем. Автор требует поцелуя написал pakmanager и Pakman. Полное раскрытие, я работаю с разработчиком.
Лично мне нравится RequireJS лучше. Это гораздо проще для отладки (вы можете иметь отдельные файлы в разработке и один развернутый файл в процессе производства) и построен на прочном "стандарте".
Ответ 2
Я написал небольшой скрипт, который позволяет асинхронную и синхронную загрузку файлов Javascript, которые могут быть полезны здесь. Он не имеет зависимостей и совместим с Node.js & CommonJS. Вы можете даже объединить несколько модулей в один файл, чтобы уменьшить HTTP-запросы на рабочих серверах. Использование довольно просто:
<script type="text/javascript" src="require.js"></script>
<script type="text/javascript">
var ModuleA = require('modulea') // Sync loading of a script in the module directory
ModuleA.funcA();
require('./path/moduleb.js', callbackB); // Async loading of a script anywhere else
function callbackB(ModuleB) {
ModuleB.funcB();
}
</script>
Более подробную информацию и код можно найти в моем блоге: http://pixelsvsbytes.com/2013/02/js-require-for-browsers-better-faster-stronger/ Код также находится на GitHub: https://github.com/letorbi/пюре /BLOB/Master/автономный /require.js
Ответ 3
Вариант Илья Харламова отличный ответ, с некоторым кодом, чтобы заставить его играть хорошо с хром-инструментами для разработчиков.
//
///- REQUIRE FN
// equivalent to require from node.js
function require(url){
if (url.toLowerCase().substr(-3)!=='.js') url+='.js'; // to allow loading without js suffix;
if (!require.cache) require.cache=[]; //init cache
var exports=require.cache[url]; //get from cache
if (!exports) { //not cached
try {
exports={};
var X=new XMLHttpRequest();
X.open("GET", url, 0); // sync
X.send();
if (X.status && X.status !== 200) throw new Error(X.statusText);
var source = X.responseText;
// fix (if saved form for Chrome Dev Tools)
if (source.substr(0,10)==="(function("){
var moduleStart = source.indexOf('{');
var moduleEnd = source.lastIndexOf('})');
var CDTcomment = source.indexOf('//@ ');
if (CDTcomment>-1 && CDTcomment<moduleStart+6) moduleStart = source.indexOf('\n',CDTcomment);
source = source.slice(moduleStart+1,moduleEnd-1);
}
// fix, add comment to show source on Chrome Dev Tools
source="//@ sourceURL="+window.location.origin+url+"\n" + source;
//------
var module = { id: url, uri: url, exports:exports }; //according to node.js modules
var anonFn = new Function("require", "exports", "module", source); //create a Fn with module code, and 3 params: require, exports & module
anonFn(require, exports, module); // call the Fn, Execute the module
require.cache[url] = exports = module.exports; //cache obj exported by module
} catch (err) {
throw new Error("Error loading module "+url+": "+err);
}
}
return exports; //require returns object exported by module
}
///- END REQUIRE FN
Ответ 4
(function () {
// c is cache, the rest are the constants
var c = {},s="status",t="Text",e="exports",E="Error",r="require",m="module",S=" ",w=window;
w[r]=function R(url) {
url+=/.js$/i.test(url) ? "" : ".js";// to allow loading without js suffix;
var X=new XMLHttpRequest(),module = { id: url, uri: url }; //according to the modules 1.1 standard
if (!c[url])
try {
X.open("GET", url, 0); // sync
X.send();
if (X[s] && X[s] != 200)
throw X[s+t];
Function(r, e, m, X['response'+t])(R, c[url]={}, module); // Execute the module
module[e] && (c[url]=module[e]);
} catch (x) {
throw w[E](E+" in "+r+": Can't load "+m+S+url+":"+S+x);
}
return c[url];
}
})();
Лучше не использовать в производстве из-за блокировки. (В node.js, require() - это блокирующий вызов).
Ответ 5
Webmake объединяет модули Node-стиля в браузер, дайте ему попробовать.
Ответ 6
Вот расширение для Lucio M. Tato фантастического ответа, который позволяет рекурсивную загрузку модулей с относительными путями.
Вот проект github для размещения решения и пример его использования:
https://github.com/trausti/TKRequire.js
Чтобы использовать TKRequire.js, включите следующую строку в свой заголовок
<script type = "text/javascript" src= "./TKRequire.js"> </script>
Затем загрузите модули так же, как в node.js:
var MyModule = require ("./relative/path/to/MyModule.js");
Ответ 7
Требуют-заглушки - обеспечивает узел-совместимый require
в браузере, решает обе модули и относительные пути. Использует технику, аналогичную TKRequire (XMLHttpRequest). Получающий код полностью watchify
для watchify
, в котором require-stub
может служить заменой для watchify
.