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

84

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

пример

var myClass = require('./js/myclass.js');
Дебра Мэддакс
источник

Ответы:

41

Вы должны смотреть на require.js или head.js для этого.

Эндрю Хэйр
источник
5
@Debra: Почему бы не зайти в раздел «Использование» на их сайте?
Гонки легкости на орбите
2
Взгляните на Require () , если вам нужно более легкое решение, чем require.js, head.js или Lab.js.
Торбен
2
... или в наши дни вы можете связать клиентский код с множеством инструментов, таких как webpack
апрель
При использовании requirejs обратите внимание на предостережение: stackoverflow.com/questions/29652716/… . В остальном у меня работает.
user180574
14

Если вы хотите использовать стиль 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;
Ренаат Де Муйнк
источник
3
Мне понравился этот ответ, потому что это не решение. Я действительно ненавижу, когда люди просто предлагают решение. Дайте ответ, который поможет им найти решение в следующий раз. Прекрасная работа!
Jasmine
13

Я задавал себе те же вопросы. Когда я изучил это, я обнаружил, что варианты подавляющие.

К счастью, я нашел эту отличную таблицу, которая поможет вам выбрать лучший загрузчик в соответствии с вашими требованиями:

https://spreadsheets.google.com/lv?key=tDdcrv9wNQRCNCRCflWxhYQ

Serby
источник
1
Интересно, означает ли наличие списка вариантов, что мы, разработчики, еще не нашли отличного способа сделать это?
Costa
7

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

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

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

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

xmojmr
источник
И помимо объединения, позволяет ли он также использовать пакеты узлов в этом пакете?
eran otzap
4

Вы можете создавать элементы в модели 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
Андре Баклунд
источник
4

Просто используйте Browserify, что-то вроде компилятора, который обрабатывает ваши файлы до того, как они поступят в производство, и упаковывает файл в пакеты.

Представьте, что у вас есть файл main.js, которому требуются файлы вашего проекта, когда вы запускаете в нем browserify, он просто обрабатывает все и создает пакет со всеми вашими файлами, позволяя использовать requireвызовы синхронно в браузере без HTTP-запросов и с очень небольшими накладными расходами, например, на производительность и размер пакета.

См. Ссылку для получения дополнительной информации: http://browserify.org/

Фернандо Мота
источник
@Dkastner уже упоминал Browserify в 2011 году. Я поискал в Google несколько альтернатив в своем ответе, но пока не знаю решения №1
xmojmr
2

Некоторые ответы уже есть, но я хотел бы указать вам на 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) версии модулей для загрузки.

Mörre
источник
1

Вот решение, использующее совершенно другой подход: упаковать все модули в объект 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Функция подвергается модулей , таким образом они могут потребоваться другие модули.

Также отображаются дополнительные свойства, такие как ссылка на глобальный объект и некоторые метаданные.

Наконец, мы выполняем программу в модуле и в заданном контексте.

Этот ответ будет наиболее полезен для тех, кто хочет иметь синхронную инструкцию require в стиле node.js в браузере и не интересуется решениями для удаленной загрузки скриптов.

Дэниел Икс Мур
источник
1

Я считаю, что проект компонента обеспечивает гораздо более оптимизированный рабочий процесс, чем другие решения (включая require.js), поэтому я бы посоветовал проверить https://github.com/component/component . Я знаю, что это немного запоздалый ответ, но может быть кому-то полезен.

Жолт Сатмари
источник
0

Вот простой способ использования требований и экспорта в вашем веб-клиенте. Это простая оболочка, которая создает глобальную переменную «пространство имен», а вы оборачиваете свой совместимый с CommonJS код в функцию «определить», например:

namespace.lookup('org.mydomain.mymodule').define(function (exports, require) {
    var extern = require('org.other.module');
    exports.foo = function foo() { ... };
});

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

https://github.com/mckoss/namespace

Маккосс
источник
0

Библиотека, требующая клиента, предоставляет асинхронную 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максимально полно реализовать функциональность в браузере. Отказ от ответственности: я написал этот модуль.

Влад Касач
источник
Есть где-нибудь полный рабочий пример? Я пытаюсь загрузить свои классы на стороне клиента, но это не сработает.
jallmer
-4

Да, это очень легко использовать, но вам нужно загрузить файл javascript в браузере с помощью тега script

<script src="module.js"></script> 

а затем пользователь в файле js, например

var moduel = require('./module');

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

Manoj
источник