Javascript-форум (https://javascript.ru/forum/)
-   Ваши сайты и скрипты (https://javascript.ru/forum/project/)
-   -   require как в ноде (https://javascript.ru/forum/project/25840-require-kak-v-node.html)

FINoM 17.02.2012 02:52

require как в ноде
 
Когда-то давно не имел представления, как сделать включение скриптов в браузере как в ноде. Сегодня опыта немного больше. Посидев пару десятков минут, сделал. Есть более функциональные импортеры модулей, этот мини скрипт создан чисто из спортивного интереса. Может быть кому-то это покажется полезным.

Функция require принимает на себя два параметра: адрес скрипта и опциональный колбек.
Если колбек не указан, то запрос на сервер будет идти синхронно, а возвращаться будет модуль. Если не указан, то возвращается null, а аргументом коллбека будет модуль.
Пример:
var module = require('module.js'); // module теперь извлекаемый модуль
//...

или
var module;
require('module.js', function( m ){
	module = m;
	//...
});


Пример файла модуля:
var local = 'local';

exports.method1 = function(){
	alert('method 1, local=' + local)
};

this.method2 = function(){
	alert('method 2')
};


Собственно, функция require:
window.require = function require(path, callback) {
	    var req = new XMLHttpRequest(),
	        module = null,
	        async = !! callback,
	        createModule = function (text) {
	            return (new Function('var exports = this;' + text + '; return this;')).call({});
	        };

	    req.open('GET', path, async);
	    req.onreadystatechange = function () {

	        if (req.readyState === 4) {
	            if (req.status === 200) {
	                module = createModule(req.responseText);
	                callback && callback(module);
	            } else {
	                throw new Error('Module ' + path + ' not found');
	            }
	        }
	    };

	    req.send(null);
	    return module;
	};

Kolyaj 17.02.2012 08:49

Цитата:

Сообщение от FINoM
require как в ноде

Нода имеет прямой доступ к файловой системе, браузер его не имеет. С учётом этого важного факта, зачем делать как в ноде?

DreamTheater 17.02.2012 11:00

http://requirejs.org/

FINoM 17.02.2012 14:11

Цитата:

Сообщение от Kolyaj
Нода имеет прямой доступ к файловой системе, браузер его не имеет. С учётом этого важного факта, зачем делать как в ноде?

Не знаю, захотелось.
Цитата:

Сообщение от DreamTheater
http://requirejs.org/

Я в курсе, спасибо.

Riim 18.02.2012 08:34

Кеширования загруженного не хватает, чтоб одно и тоже по 5 раз не грузилось.

melky 18.02.2012 11:30

а если скрипт на другом домене ?

tadjik1 18.02.2012 13:33

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

Nekromancer 18.02.2012 17:07

tadjik1,
Тогда вся концепция экспортов разлетается. В общем загрузка модулей это актуально, но таким подходом написанном на коленке ничего не добиться.

FINoM 18.02.2012 18:04

Цитата:

Сообщение от Riim
Кеширования загруженного не хватает, чтоб одно и тоже по 5 раз не грузилось.

Эм, кеширование, обычно, делают на сервере.
Цитата:

Сообщение от melky
а если скрипт на другом домене ?

Сам знаешь, через YQL :D
Цитата:

Сообщение от Nekromancer
В общем загрузка модулей это актуально, но таким подходом написанном на коленке ничего не добиться.

Ну я не претендую на уникальность или полезность. Можно, например, еще и добавить загрузку списка модулей, как в requirejs.

FINoM 18.02.2012 21:32

Nekromancer, а какой подход по-твоему был бы хорош?

Nekromancer 19.02.2012 01:29

Цитата:

Сообщение от FINoM
Эм, кеширование, обычно, делают на сервере.

Кеширование обычно делают везде. Если брать ту ситуацию о которой вам сказали, речь идёт о том, что не нужно загружать несколько раз данные с сервера, которые заведомо не поменяются в период сессии. Лёгкий кеш в общем то.
Цитата:

Сообщение от FINoM
Nekromancer, а какой подход по-твоему был бы хорош?

Ну, так уж сложилось, что я сейчас занят разработкой такого проекта по месту работы, по этому всё не расскажу.
Во первых конечно система модулей должна быть от части уникальной, для той или иной архитектуры сервера.
Во вторых должна быть какая то система, а не как например попытки вконтакт сделать нечто подобное.
Хороший пример в Яндексе, во внутреннем коде не копался, но это наверно единственные кто для синхронной загрузки модуля используют document.write. Это именно тут случай, когда нужен это инструмент.
Ещё просматривал всякие реализации, даже посмотрел видео презентацию от "ведущего" разработчика в мейл.ру. Меня вот например не могло не "порадовать" исполнение кода через onclick и называя это всё "возможностью из коробки".

FINoM 19.02.2012 02:09

Цитата:

Сообщение от Nekromancer
Если брать ту ситуацию о которой вам сказали, речь идёт о том, что не нужно загружать несколько раз данные с сервера, которые заведомо не поменяются в период сессии.

Кеширование должно делаться средствами сервера, то бишь заголовками, если ты не в курсе.
Цитата:

Сообщение от Nekromancer
Ну, так уж сложилось, что я сейчас занят разработкой такого проекта по месту работы, по этому всё не расскажу.

Когда будет возможность расскажи.

Nekromancer 19.02.2012 02:55

Цитата:

Сообщение от FINoM
Кеширование должно делаться средствами сервера, то бишь заголовками, если ты не в курсе.

Прости, но по моему ты не в курсе. Кеширование это не только кеширование заголовками. Можешь почитать про эту тему на данном ресурсе, можешь на любом другом.
Да, вот ещё. Почему должно? Кеширование заголовками это один способ, но не единственный.
Например часто можно на вопрос - Почему сервер не присылает Etag? - услышать, - А зачем? Last-Modified достаточно.
А ещё аргументируют это лишней нагрузкой на сервер :)

FINoM 19.02.2012 03:47

Цитата:

Сообщение от Nekromancer
Прости, но по моему ты не в курсе. Кеширование это не только кеширование заголовками. Можешь почитать про эту тему на данном ресурсе, можешь на любом другом.

Я не понимаю зачем в данном случае кеширование. Типа дурак два раза вызовет модуль? Не так уж и страшно, как по мне. Или ты имеешь в виду кеширование в одном из локальных хранилищ? Если да, то я не просто не согласен, а еще и удивлен. Или ты вообще не об этом? Просто выражайся яснее, кеширование — понятие растяжимое.

Riim 19.02.2012 04:57

Цитата:

Сообщение от FINoM
Типа дурак два раза вызовет модуль?

это как бы обычная ситуация, не знаю как на клиенте, но в nodejs у меня ко многим модулям, например, fs подключается (т. е. подгрузка одних модулей внутри других, что-то вроде описания зависимостей).

FINoM, и вообще ты так споришь против кеширования, как будто это что-то сложное, там же 2 строчки дописать и готово.

FINoM 19.02.2012 05:02

Цитата:

Сообщение от Riim
FINoM, и вообще ты так споришь против кеширования, как будто это что-то сложное, там же 2 строчки дописать и готово.

Вот именно, я то тут причем :D
Как кажется правильным так и пишу.

Riim 19.02.2012 05:05

Цитата:

Сообщение от FINoM
Как кажется правильным так и пишу

ну так ты исключаешь для себя вот это:
Цитата:

Сообщение от Riim
т. е. подгрузка одних модулей внутри других, что-то вроде описания зависимостей

, или нет?

FINoM 19.02.2012 05:15

Riim, мне тупо было интересно как зареквайрить скрипт подобно ноде. Я сделал то что хотел.
А здесь можно добавить очень много полезных вещей, как вызов сразу нескольких модулей (как в requirejs), совмещение нескольких модулей в одном, пресловутое кеширование... Но делать это просто лень. Я не для использования писал этот код, а для того, чтоб показать забавную вещицу (по крайней мере, для меня забавную). Если хотите большего, не проблема, пишите, я не накладываю никаких ограничений на свой код :D

Kolyaj 19.02.2012 09:41

Цитата:

Сообщение от Nekromancer
Хороший пример в Яндексе, во внутреннем коде не копался, но это наверно единственные кто для синхронной загрузки модуля используют document.write.

Это где?

Nekromancer 19.02.2012 11:00

Kolyaj,
Это в Яндекс картах, флаг useDocumentWrite.

Nekromancer 19.02.2012 11:02

Цитата:

Сообщение от FINoM
Или ты имеешь в виду кеширование в одном из локальных хранилищ? Если да, то я не просто не согласен, а еще и удивлен.

Если бы я имел введу его. Почему ты не согласен?

Kolyaj 19.02.2012 13:59

Цитата:

Сообщение от Nekromancer
Это в Яндекс картах, флаг useDocumentWrite.

Всякое JS-API это не то же самое, что обычные скрипты. Не надо их сравнивать.

Nekromancer 19.02.2012 15:35

Kolyaj,
тут разве есть что то плохое?

FINoM 20.02.2012 05:29

Цитата:

Сообщение от Nekromancer
Если бы я имел введу его. Почему ты не согласен?

Зачем? Нет, если есть задача сократить количество запросов к серверу к минимуму или реализовать возможность работы оффлайн, то да. Такая задача стоит крайне редко.

Nekromancer 20.02.2012 10:54

FINoM,
Я не понимаю по каким данным ты судишь, что крайне редко. Для обычных сайтов - да, вообще не надо. Но для них и модули не нужны.
Помнится ты сам просил уроки о том, как создавать правильные веб приложения.

Kolyaj 20.02.2012 12:39

Цитата:

Сообщение от Nekromancer
тут разве есть что то плохое?

Подключать модули document.write-ом? Плохо то, что делается много запросов, когда можно сделать один.
В случае API карт, очевидно, подключаются не модули, а сам API.

Nekromancer 20.02.2012 15:09

Kolyaj,
Этим же document.write можно запросить сразу все модули которые в зависимости, то есть будет на один запрос больше.

Kolyaj 20.02.2012 15:20

А почему сразу все не запросить? Без document.write?

Nekromancer 20.02.2012 15:43

Kolyaj,
потому, что формируется один статический файл в котором основное управление. Я думаю можно конечно вставить в тело документа все нужные скрипты для данной страницы. Но я решил попробовать систему хранения скриптов в storage. Если пользователь активный посетитель ресурса, то у него должна быть уже большая часть скриптов.

П.С. Это конечно сомнительное преимущество, но всё же.

FINoM 20.02.2012 18:57

Цитата:

Сообщение от Nekromancer
Но для них и модули не нужны.

Значит, если используются модули, значит их нужно сохранять их в локальном хранилище, так?
Цитата:

Сообщение от Nekromancer
Помнится ты сам просил уроки о том, как создавать правильные веб приложения.

А ничего, что нужно сперва смотреть задачу, уже потом решать, как её решать, а не наоборт?

Nekromancer 20.02.2012 18:59

Цитата:

Сообщение от FINoM
Значит, если используются модули, значит их нужно сохранять их в локальном хранилище, так?

Нет.
Цитата:

Сообщение от FINoM
А ничего, что нужно сперва смотреть задачу, уже потом решать, как её решать, а не наоборт?

Что?

FINoM 20.02.2012 19:00

Думать, как её решать. В спешке писал.
Цитата:

Сообщение от Nekromancer
Нет.

Ну и что ты мне пытаешься доказать?

Nekromancer 20.02.2012 19:08

Цитата:

Сообщение от FINoM
Ну и что ты мне пытаешься доказать?

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

FINoM 20.02.2012 19:12

Цитата:

Сообщение от Nekromancer
Что же все такие эмоциональные пошли. Ничего я тебе не доказываю, вы просто вертитесь вокруг провокационной фразы пытаясь доказать, что то в ответ, подкрепляя это предположениями.

(Теперь моя очередь) Что?

FINoM 08.05.2012 21:17

Развил сабж: http://pastebin.com/zWUcBare
Теперь можно запрашивать модули кучей:
require(['m1', 'm2']);
Если не использовать коллбек, то объекты просто конкатенируются. Например:
// m1
this.method1 = function(){};
this.method2 = function(){};

// m2
this.method3 = function(){};
this.method4 = function(){};


require(['m1', 'm2']);
Возвращает объект с этими четырьмя методами.
Если использовать коллбек, то в него передаются модули в том же порядке, что и массив скриптов:
require(['m1', 'm2'], function( m1, m2 ){ ... });

Добавил пару настроек:
require.PATH = '/'; // папка, в которой лежат модули, например, /js/modules
require.POSTFIX = ''; // постфикс (ко) адреса скрипта, например, '.js' или '.module.js'
require.CONCAT_ALL = false; // в коллбек передаётся один аргумент: объект со всеми модулями сразу
// например
require(['m1', 'm2'], function( all ){ 
 // all == {method1: ...,method2: ...,method3: ...,method4: ... }
 });
В будущем все-таки добавлю кеширование и запросы к модулям на другом домене (cors)

B~Vladi 10.05.2012 15:54

Модульность это хорошо. Но все почему-то забывают, что скрипту могут понадобиться и другие данные, например HTML-разметка (шаблоны) или стили.

Поэтому нужно грузить XML-файл, в котором будут все эти данные. Что бы это было на уровне API функции require.

Это ИМХО)

FINoM 10.05.2012 17:45

Цитата:

Сообщение от B~Vladi
Поэтому нужно грузить XML-файл, в котором будут все эти данные.

С чего такая страсть к XML?
Цитата:

Сообщение от B~Vladi
Но все почему-то забывают, что скрипту могут понадобиться и другие данные, например HTML-разметка (шаблоны) или стили.

Ну я допилил скрипт только исходя из моей задачи. Остальное мне просто не нужно. Стилями управляю через less, а в ejs есть своя функция для запроса шаблонов.

B~Vladi 10.05.2012 21:29

Цитата:

Сообщение от FINoM
С чего такая страсть к XML?

Почему страсть? Просто он для этой цели подходит лучше всего.

FINoM 10.05.2012 21:31

Цитата:

Сообщение от B~Vladi
Просто он для этой цели подходит лучше всего.

Не понимаю. Я просто хотел запрашивать скрипты. Зачем мне XML?

Да и вообще, к черту XML, если есть JSON. По крайней мере 99% задач, которые решаются XML можно решить JSON. Он компактнее, читабельнее, дружит с JS.

B~Vladi 10.05.2012 22:38

Цитата:

Сообщение от FINoM
читабельнее

Это дело вкуса.
Цитата:

Сообщение от FINoM
Зачем мне XML?

Тебе может и незачем. Я вообще так сказал, мысли в слух.
Цитата:

Сообщение от FINoM
к черту XML, если есть JSON

XML тут всё же лучше. Например, можно изначально писать js, html и css в одном файле, не думая о экранировании. При этом будет корректно работать подсветка в IDE. С JSON этого не будет. Придется писать дополнительную логику соединения данных.


Часовой пояс GMT +3, время: 19:45.