Нужен стиль в JavaScript-браузере?

Существуют ли библиотеки для браузера в браузере, которые обеспечивают такую же гибкость/модульность/простоту использования, как require узла?

Для того, чтобы предоставить более подробную информацию: причина require настолько хороша, что она:

  1. Позволяет динамически загружать код из других мест (что, на мой взгляд, стилистически лучше, чем связывание всего кода в HTML)
  2. Он обеспечивает согласованный интерфейс для построения модулей
  3. Модулям легко зависеть от других модулей (поэтому я мог бы написать, например, API, который требует jQuery, поэтому я могу использовать jQuery.ajax()
  4. Загруженный 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() - это блокирующий вызов).

Ответ 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.