JavaScript require() на стороне клиента
Можно ли использовать require()
(или что-то подобное) на стороне клиента?
пример
var myClass = require('./js/myclass.js');
14 ответов
Для этого я использовал http://browserify.org/. Это также позволяет мне интегрировать модули Node.js в мой клиентский код.
Я писал об этом здесь: добавьте node.js/CommonJS style require() в клиентский JavaScript с помощью browserify
Если вы хотите иметь стиль Node.js 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
Я обнаружил, что в целом рекомендуется предварительно обрабатывать сценарии во время компиляции и связывать их в один (или очень мало) пакетов с 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
Просто используйте Browserify, что-то вроде компилятора, который обрабатывает ваши файлы перед тем, как он отправляется в производство, и упаковывает файл в пакеты.
Представьте, что у вас есть файл main.js, который требует файлы вашего проекта. Когда вы запускаете в нем browserify, он просто обрабатывает все и создает пакет со всеми вашими файлами, что позволяет использовать require
например, синхронные вызовы в браузере без HTTP-запросов и с очень небольшими накладными расходами для производительности и размера пакета.
Смотрите ссылку для получения дополнительной информации: http://browserify.org/
Вы можете создавать элементы в 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
Некоторые ответы уже есть, но я хотел бы указать вам на 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", а также модуль "own-app-module1", а затем запускается функция обратного вызова. Создается новая песочница "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
Этот внешний контекст предоставляет некоторую переменную, к которой у модулей есть доступ.
require
Функция доступна для модулей, поэтому им могут потребоваться другие модули.
Дополнительные свойства, такие как ссылка на глобальный объект и некоторые метаданные, также доступны.
Наконец, мы выполняем программу внутри модуля и данного контекста.
Этот ответ будет наиболее полезен для тех, кто хочет использовать синхронный стиль node.js в браузере и не интересуется решениями по удаленной загрузке скриптов.
Я считаю, что проект компонента предоставляет гораздо более упорядоченный рабочий процесс, чем другие решения (включая require.js), поэтому я бы посоветовал проверить https://github.com/component/component. Я знаю, что это немного запоздалый ответ, но может быть полезным для кого-то.
Вот легкий способ использовать require и export в вашем веб-клиенте. Это простая оболочка, которая создает глобальную переменную "пространство имен", и вы оборачиваете свой 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 src="module.js"></script>
а затем пользователь в JS-файле, как
var moduel = require('./module');
Я делаю приложение с использованием электронов, и оно работает, как ожидалось.