Можно ли использовать require()
(или что-то подобное) на стороне клиента?
Пример
var myClass = require('./js/myclass.js');
Можно ли использовать require()
(или что-то подобное) на стороне клиента?
Пример
var myClass = require('./js/myclass.js');
Для этого вам следует обратиться к require.js или head.js.
Я использовал browserify. Он также позволяет мне интегрировать модули Node.js в свой код на стороне клиента.
Я писал об этом здесь: Добавить Node.js/стиль CommonJS require() для клиентского JavaScript с браузером
Если вы хотите иметь Node.js style require
, вы можете использовать что-то вроде этого:
var require = (function () {
var cache = {};
function loadScript(url) {
var xhr = new XMLHttpRequest(),
fnBody;
xhr.open('get', url, false);
xhr.send();
if (xhr.status === 200 && xhr.getResponseHeader('Content-Type') === 'application/x-javascript') {
fnBody = 'var exports = {};\n' + xhr.responseText + '\nreturn exports;';
cache[url] = (new Function(fnBody)).call({});
}
}
function resolve(module) {
//TODO resolve urls
return module;
}
function require(module) {
var url = resolve(module);
if (!Object.prototype.hasOwnProperty.call(cache, url)) {
loadScript(url);
}
return cache[url];
}
require.cache = cache;
require.resolve = resolve;
return require;
}());
Остерегайтесь: этот код работает, но является неполным (особенно для разрешения URL) и не реализует все функции Node.js(я просто поставил это вместе прошлой ночью). ВЫ НЕ ДОЛЖНЫ ИСПОЛЬЗОВАТЬ ЭТОТ КОД в реальных приложениях, но это дает вам отправную точку. Я тестировал его с помощью этого простого модуля, и он работает:
function hello() {
console.log('Hello world!');
}
exports.hello = hello;
Я задал себе те же самые вопросы. Когда я заглянул в нее, я нашел выбор подавляющим.
К счастью, я нашел эту отличную таблицу, которая поможет вам выбрать лучший загрузчик на основе ваших требований:
https://spreadsheets.google.com/lv?key=tDdcrv9wNQRCNCRCflWxhYQ
Взгляните на проект requirejs.
Я обнаружил, что в общем случае рекомендуется выполнять предварительную обработку сценариев во время компиляции и связывать их в одном (или очень немногих) пакетах с заменой require
на некоторую "легкую прокладку" также во время компиляции.
Я искал следующие "новые" инструменты, которые могли бы это сделать
И уже упомянутый browserify
должен также хорошо соответствовать - http://esa-matti.suuronen.org/blog/2013/04/15/asynchronous-module-loading-with-browserify/
Описание более позднего - Связь между CommonJS, AMD и RequireJS?
Подробное обсуждение различных фреймворков модулей и require()
им нужно в Addy Osmani - Написание модульного JavaScript с AMD, CommonJS и ES Harmony
Вы можете создавать элементы в DOM, который загружает элементы.
Подобно такому:
var myScript = document.createElement('script'); // Create new script element
myScript.type = 'text/javascript'; // Set appropriate type
myScript.src = './js/myclass.js'; // Load javascript file
Просто используйте Browserify, что-то вроде компилятора, который обрабатывает ваши файлы, прежде чем он вступает в производство, и упаковывает файл в пакеты.
Подумайте, что у вас есть файл main.js, который требует файлов вашего проекта, когда вы запускаете в нем браузер, он просто обрабатывает все и создает пакет со всеми вашими файлами, позволяя синхронно использовать вызовы require
в браузер без HTTP-запросов и с очень небольшими накладными расходами для производительности и размера пакета, например.
Смотрите ссылку для получения дополнительной информации: http://browserify.org/
Некоторые ответы уже есть, но я хотел бы указать вам на YUI3 и загрузку модуля по требованию. Он работает как на сервере (node.js), так и на клиенте. У меня есть демонстрационный веб-сайт, в котором используется тот же JS-код, который работает на любом клиенте или сервере для создания страниц, но этот другой раздел.
YUI3: http://developer.yahoo.com/yui/3/
Видео: http://developer.yahoo.com/yui/theater/
Пример:
(предварительное условие: загружены основные функции YUI3 в 7k yui.js)
YUI({
//configuration for the loader
}).use('node','io','own-app-module1', function (Y) {
//sandboxed application code
//...
//If you already have a "Y" instance you can use that instead
//of creating a new (sandbox) Y:
// Y.use('moduleX','moduleY', function (Y) {
// });
//difference to YUI().use(): uses the existing "Y"-sandbox
}
Этот код загружает модули YUI3 "node" и "io", а модуль "собственный-приложение-модуль1", а затем запускается функция обратного вызова. Создается новая песочница "Y" со всеми функциями YUI3 и own-app-module1. Ничего не отображается в глобальном пространстве имен. Загрузка модулей (.js файлов) осуществляется загрузчиком YUI3. Он также использует (необязательно, не показывать здесь) конфигурацию для выбора версии -debug или -min (ified) модулей для загрузки.
Здесь решение, которое принимает совсем другой подход: упаковывает все модули в объект JSON и требует модулей путем чтения и выполнения содержимого файла без дополнительных запросов.
https://github.com/STRd6/require/blob/master/main.coffee.md
STRd6/require зависит от наличия пакета JSON во время выполнения. Для этого пакета создается функция require
. Пакет содержит все файлы, которые может потребовать ваше приложение. Дополнительные HTTP-запросы не выполняются, потому что пакет связывает все зависимости. Это так близко, что вы можете получить стиль Node.js на клиенте.
Структура пакета выглядит следующим образом:
entryPoint: "main"
distribution:
main:
content: "alert(\"It worked!\")"
...
dependencies:
<name>: <a package>
В отличие от Node пакет не знает его внешнего имени. Это зависит от pacakge, включая зависимость, чтобы назвать его. Это обеспечивает полную инкапсуляцию.
Учитывая все, что устанавливает здесь функцию, которая загружает файл из пакета:
loadModule = (pkg, path) ->
unless (file = pkg.distribution[path])
throw "Could not find file at #{path} in #{pkg.name}"
program = file.content
dirname = path.split(fileSeparator)[0...-1].join(fileSeparator)
module =
path: dirname
exports: {}
context =
require: generateRequireFn(pkg, module)
global: global
module: module
exports: module.exports
PACKAGE: pkg
__filename: path
__dirname: dirname
args = Object.keys(context)
values = args.map (name) -> context[name]
Function(args..., program).apply(module, values)
return module
Этот внешний контекст предоставляет некоторую переменную, к которой модули имеют доступ.
Функция A require
подвергается воздействию модулей, поэтому им могут потребоваться другие модули.
Дополнительные свойства, такие как ссылка на глобальный объект и некоторые метаданные также подвергаются.
Наконец, мы выполняем программу внутри модуля и заданного контекста.
Этот ответ будет наиболее полезен тем, кто хочет иметь синхронный Node.js стиль require statement в браузере и не заинтересован в удаленных решениях загрузки script.
Я нахожу, что компонентный проект дает гораздо более оптимизированный рабочий процесс, чем другие решения (включая require.js), поэтому я бы посоветовал проверить https://github.com/component/component. Я знаю, что это немного поздний ответ, но может быть полезен кому-то.
Здесь легкий способ использования требует и экспортирует в ваш веб-клиент. Это простая оболочка, которая создает глобальную переменную "namespace", и вы переносите свой совместимый с CommonJS код в функцию "define" следующим образом:
namespace.lookup('org.mydomain.mymodule').define(function (exports, require) {
var extern = require('org.other.module');
exports.foo = function foo() { ... };
});
Больше документов здесь:
Библиотека clientide-require предоставляет асинхронную функцию load()
которую можно использовать для загрузки любого файла JS или модуля NPM (который использует module.exports
), любого файла .css
, любого .json
, любого .html
, любого любого другого файла в виде текст.
например, npm install clientside-require --save
<script src = '/node_modules/clientside-require/dist/bundle.js'></script>
<script>
load('color-name') // an npm module
.then(color_name=>{
console.log(color_name.blue); // outputs [0, 0, 255]
})
</script>
Действительно интересная часть этого проекта заключается в том, что внутри любого скрипта load()
ed вы можете использовать синхронную функцию require()
же, как и в файле node.js!
например,
load('/path/to/functionality.js')
и внутри /path/to/functionality.js
:
var query_string = require("qs") // an npm module
module.exports = function(name){
return qs.stringify({
name:name,
time:new Date()
}
}
Эта последняя часть, реализующая синхронный метод require()
, позволяет использовать пакеты NPM, созданные для запуска на сервере.
Этот модуль был разработан для максимально полной реализации require
функциональности в браузере. Отказ от ответственности: я написал этот модуль.
Да, это очень легко использовать, но вам нужно загрузить javascript файл в браузере тегом script
<script src="module.js"></script>
а затем пользователь в js файле, например
var moduel = require('./module');
Я делаю приложение с использованием электрона, и оно работает как ожидалось.