Существуют ли какие-либо библиотеки для встроенного в браузер 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 ).