Существуют ли какие-либо библиотеки для встроенного в браузер javascript, которые обеспечивают такую же гибкость / модульность / простоту использования, что и Node 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, который вообще не загрязняет глобальное пространство имен, но по-прежнему позволяет мне загружать и использовать библиотеки (как это делает node).
ОБНОВЛЕНИЕ 2020 ГОДА: модули теперь являются стандартными в ES6, и с середины 2020 года они изначально поддерживаются большинством браузеров. . Модули поддерживают как синхронную, так и асинхронную (с использованием Promise) загрузку. Моя текущая рекомендация заключается в том, что в большинстве новых проектов следует использовать модули ES6 и использовать транспилятор для возврата к одному файлу JS для устаревших браузеров.
Как правило, сегодня полоса пропускания намного шире, чем когда я изначально задавал этот вопрос. Так что на практике вы могли бы разумно выбрать всегда использовать транспилятор с модулями ES6 и сосредоточить свои усилия на эффективности кода, а не на сети.
ПРЕДЫДУЩИЙ РЕДАКТИРОВАНИЕ (или если вам не нравятся модули ES6): с момента написания этого я широко использовал RequireJS (который теперь имеет гораздо более четкую документацию). На мой взгляд, RequireJS был правильным выбором. Хочу пояснить, как работает система, для людей, которые так же запутались, как и я:
Можно использовать require
в повседневной разработке. Модуль может быть чем угодно, возвращаемым функцией (обычно объектом или функцией), и имеет область видимости как параметр. Вы также можете скомпилировать свой проект в один файл для развертывания r.js
(на практике это почти всегда быстрее, даже если require
скрипты можно загружать параллельно).
Основное различие между RequireJS и типом node-style require, подобным использованию browserify (классный проект, предложенный tjameson), заключается в том, как модули проектируются и требуются:
- RequireJS использует AMD (определение асинхронного модуля). В AMD
require
принимает список модулей (файлов javascript) для загрузки и функцию обратного вызова. Когда он загружает каждый из модулей, он вызывает обратный вызов с каждым модулем в качестве параметра для обратного вызова. Таким образом, он действительно асинхронный и поэтому хорошо подходит для Интернета. - Node использует CommonJS. В CommonJS
require
это блокирующий вызов, который загружает модуль и возвращает его как объект. Это отлично работает для Node, потому что файлы считываются из файловой системы, что достаточно быстро, но плохо работает в Интернете, поскольку синхронная загрузка файлов может занять намного больше времени.
На практике многие разработчики использовали Node (и, следовательно, CommonJS) еще до того, как увидели AMD. Кроме того, многие библиотеки / модули написаны для CommonJS (путем добавления элементов в exports
объект), а не для AMD (путем возврата модуля из define
функции). Поэтому многие веб-разработчики, перешедшие на Node, хотят использовать библиотеки CommonJS в Интернете. Это возможно, так как загрузка с <script>
тега блокируется. Такие решения, как browserify, берут модули CommonJS (Node) и обертывают их, чтобы вы могли включать их в теги сценария.
Поэтому, если вы разрабатываете свой собственный многофайловый проект для Интернета, я настоятельно рекомендую RequireJS, поскольку это действительно модульная система для Интернета (хотя, честно говоря, я считаю AMD гораздо более естественной, чем CommonJS). В последнее время это различие стало менее важным, поскольку RequireJS теперь позволяет вам по существу использовать синтаксис CommonJS. Кроме того, RequireJS можно использовать для загрузки модулей AMD в Node (хотя я предпочитаю node-amd-loader ).
источник
Ответы:
Проверьте Эндер . Он делает много этого.
Кроме того, браузер работает очень хорошо. Я использовал require-kiss ¹, и он работает. Наверное, есть и другие.
Я не уверен насчет RequireJS. Это просто не то же самое, что и узел. У вас могут возникнуть проблемы с загрузкой из других мест, но это может сработать. Пока есть метод provide или что-то, что можно вызвать.
TL; DR - я бы порекомендовал просмотреть или потребовать поцелуй.
Обновить:
1: require-kiss теперь мертв, и автор удалил его. С тех пор я без проблем использую RequireJS. Автор требует поцелуя написал pakmanager и Pakman . Полное раскрытие, работаю с разработчиком.
Лично мне больше нравится RequireJS. Его намного проще отлаживать (вы можете иметь отдельные файлы в разработке и один развернутый файл в производстве) и построен на твердом «стандарте».
источник
Я написал небольшой скрипт, который позволяет асинхронно и синхронно загружать файлы Javascript, которые могут быть здесь полезны. Он не имеет зависимостей и совместим с Node.js и CommonJS. Установка довольно проста:
$ npm install --save @tarp/require
Затем просто добавьте следующие строки в свой HTML, чтобы загрузить основной модуль:
<script src="/node_modules/@tarp/require/require.min.js"></script> <script>Tarp.require({main: "./scripts/main"});</script>
Внутри вашего основного модуля (и, конечно, любого подмодуля) вы можете использовать то,
require()
что вы знаете из CommonJS / NodeJS. Полную документацию и код можно найти на GitHub .источник
myFunction
вalert("hello")
. Я звонюmain.myFunction()
? Это не сработает?Tarp.require({ expose: true });
чтобы он работал? Как в вашем тесте?Я понимаю, что могут быть новички, желающие организовать свой код. Это 2020 год , и если вы рассматриваете модульное приложение JS, вам следует начать работу с npm и Webpack прямо сейчас.
Вот несколько простых шагов, чтобы начать работу:
npm init -y
чтобы инициализировать проект npmnpm install webpack webpack-cli
Обратите особое внимание на
_bundle.js
файл - это будет последний JS-файл, сгенерированный webpack, вы не будете изменять его напрямую (продолжайте читать).<project-root>/app.js
в котором вы будете импортировать другие модули:const printHello = require('./print-hello'); printHello();
print-hello.js
модуля:module.exports = function() { console.log('Hello World!'); }
<project-root>/webpack.config.js
и скопируйте следующее:var path = require('path'); module.exports = { entry: './app.js', output: { path: path.resolve(__dirname), filename: '_bundle.js' } };
В приведенном выше коде есть 2 пункта:
app.js
- это место, где вы будете писать свой JS-код. Он импортирует другие модули, как показано выше._bundle.js
- это ваш последний пакет, сгенерированный webpack. Это то, что ваш html увидит в конце.-7. Откройте свой
package.js
и заменитеscripts
следующей командой:"scripts": { "start": "webpack --mode production -w" },
app.js
и генерировать_bundle.js
файл, выполнив:npm start
.источник
Вариант отличного ответа Ильи Харламова с некоторым кодом, чтобы он хорошо работал с инструментами разработчика Chrome.
// ///- 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
источник
(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 () - это хорошо блокирующий вызов).
источник
Webmake связывает модули в стиле узла с браузером, попробуйте.
источник
Require-stub - обеспечивает соответствие узлов
require
в браузере, разрешает как модули, так и относительные пути. Использует технику, аналогичную TKRequire (XMLHttpRequest). Результирующий код полностьюrequire-stub
доступен для просмотра и может служить заменойwatchify
.источник
Вот расширение фантастического ответа Лучио М. Тато, которое позволяет рекурсивно загружать модули с относительными путями.
Вот проект github для размещения решения и пример его использования:
https://github.com/trausti/TKRequire.js
Чтобы использовать TKRequire.js, включите следующую строку в свой заголовок
Затем загрузите модули, как в node.js:
источник