JavaScript require() на стороне клиента

Можно ли использовать require() (или что-то подобное) на стороне клиента?

пример

var myClass = require('./js/myclass.js');

14 ответов

Для этого вам следует обратиться к require.js или head.js.

Для этого я использовал 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

Взгляните на проект http://requirejs.org/.

Я обнаружил, что в целом рекомендуется предварительно обрабатывать сценарии во время компиляции и связывать их в один (или очень мало) пакетов с require переписывается в какую-то "легкую шимму" также во время компиляции.

Я гуглил следующие "новые" инструменты, которые должны быть в состоянии сделать это

И уже упоминалось browserify также должно подходить достаточно хорошо - http://esa-matti.suuronen.org/blog/2013/04/15/asynchronous-module-loading-with-browserify/

Что такое модульные системы?

Просто используйте 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() { ... };
});

Больше документов здесь:

https://github.com/mckoss/namespace

Библиотека 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');

Я делаю приложение с использованием электронов, и оно работает, как ожидалось.

Другие вопросы по тегам