модульность для js
Документация и исходники тут https://github.com/vflash/scmod
В свое время пробовал асинхронно загружать по требованию но переизбыток асинхронности усложняет код. Позже стал просто объединять файлы в один, а для описания связей использовал отдельные файлы. Программируя под nodejs оценил удобство когда каждый файл имеет свою область видимости. Появилась идея сделать менеджер js-файлов в виде веб сервиса. Сервису указываем корневой модуль, а он формирует список файлов и отдает js код для подключения этих файлов через прокси который оборачивает исходник в функцию(свою область видимости) . То как сделано в node.js на клиенте повторить не получиться, так как в ноде файлы грузятся синхронно по требованию. Потому для клиента необходимо вначале вычислять какие и в какой последовательность файлы нужно грузить. Если держать структуру модуля в js-коде(как в ноде), то для вычисления списка файлов потребуется загружать и парсить все эти файлы. Но это увеличивает общее время время загрузки страницы. Когда количество файлов в несколько десятков это становиться неудобно во время разработки. Поэтому и по опыту использования "отдельных файлов", в качестве структуры модуля выступает отдельный json файл. Описание модуля выглядит примерно так // какойто модуль /js/zzz { "modules": { "core": "../core/core.json", "xxx": "./xxx.json" }, "scripts": [ "./common.js", "./code.js", "./init.js" ] } // модуль обшего функционала ../core/core.json { "scripts": [ "./core.js", "./core-cookie.js", "./core-xhr.js" ] } // еще какойто модуль ./xxx.json { "modules": { "core": "../core/core.json" }, "scripts": [ "./xxx1.js", "./xxx2.js" ] } в результате должны быть подключены файлы: Код:
/js/core/core.js Код:
http://scmod.vflash.ru/file/1/-,core,xxx/http/demo.com/js/zzz/common.js если нужен объект который будет общим для файлов модуля но недоступен другим модулям то структуре нужно создать связь с указанием пути как true { "modules": { "core": "../core/core.json", "xxx": "./xxx.json", "ee": true }, "scripts": [ "./common.js", "./code.js", "./init.js" ] } если нужен виртуальный модуль то так: { "modules": { "core": "../core/core.json", "xxx": "./xxx.json", "vvv": "global:vvvv" }, "scripts": [ "./common.js", "./code.js", "./init.js" ] } Если необходимо чтобы переменная "module" была названа по другому то в структуре необходимо указать: { "alias": "ddd", "modules": { "core": "../core/core.json", "xxx": "./xxx.json", "vvv": "global:vvvv" }, "scripts": [ "./common.js", "./code.js", "./init.js" ] } Где-то серьезно опробовать этот менеджер еше не приходилось. Написал прототип на node.js , но реализация такая только чтоб проверить и попробовать использовать. В перспективе в структуре можно хранить и структуру CSS файлов. Исходник сервиса тут https://github.com/vflash/scmod Для пробы запустил сервис по адресу http://scmod.vflash.ru подключать примерно так http://scmod.vflash.ru/sandbox?src=h...da/common.json сборка в один файл выглядит так http://scmod.vflash.ru/scripts?src=h...da/common.json код сырой потому уронить можно в три счета. |
Если в модуле будет setTimiout или ajax-запрос
которые обращаются к глобальным переменным-то будет ошибка |
Цитата:
Как-то у тебя сложно всё. Я просто пишу в каждом файле инструкции, указывающие от каких файлов зависит текущий. Не надо никаких дополнительных конфигов. https://github.com/Kolyaj/BuildJS |
Kolyaj,
мне удобнее отдельный файл структуры. в этом-же файле можно указывать используемые CSS. на вкус и цвет ... |
добавил возможность указывать зависимые CSS файлы в пакет.
// какойто модуль /js/zzz { "styles": [ "./element.css" ] } в итоге сервис http://scmod.vflash.ru/sandbox?src=.... вернет js код который подключит через document.write(...), JS и CSS файлы. сервис http://scmod.vflash.ru/styles?src=.... соберет все css файлы в один и вернет его. также опробовал перевод на другие языки. Для этого в модули описываю матрицу замены строк: // какойто модуль /js/zzz { "langs": { "текст который требует перевода": { "ru": "текст перевода", "en": "the translation", "vn": "bản dịch", .... }, ...... } } через сервис http://scmod.vflash.ru/scripts?lang=vn&src=.... получаю js-код уже на другом языке. В JS-коде заменяются строки только в "двойных кавычках". а если запросить http://scmod.vflash.ru/langs?src=http://..../xxx.json то выдаст список строк для которых нужен перевод. |
У самого сейчас возникла необходимость создать такой инструмент для проекта.
Спасибо за исходник, посмотрю Ваш подход. Когда-то колупался в BuilderJS от Kolyaj, тоже прикольно :) |
Цитата:
|
Цитата:
|
Цитата:
Я знаю, как его отрефакторить, чтобы было всё красиво и понятно, но мне лень, раз всё и так работает. |
Лучше сделать, пока всё помнишь :)
Развитие не предполагается разве? |
Куда развитие? Свою задачу скрипт выполняет.
Есть одна вещь, которую можно было бы добавить. Как решу добавлять, так и отрефакторю. Цитата:
|
Цитата:
|
продолжаю развивать это направление.
утилита функционально не выросла , но в качестве код подрос. использую его в проекте wada.vn и в своем небольшом сервисе. На практике большим плюсом стало то, что в модуле сразу описываю зависимости css-файлов. Уже и забыл про ошибки на подобии случайной глобальной переменной. Или в каком-то файле не указал "use strict". на будущее есть идея - собирать js не в один файл, а выделять общее для всех страниц ядро. в общем получался простой и практичный инструмент. исходник - https://github.com/vflash/scmod npm - https://npmjs.org/package/scmod демо - http://scmod.vflash.ru/sandbox?src=h...eedreader.json |
Реализовал функционал подмены адресов. Адрес модуля сверяется с таблицей и заменяется на другой.
Используя подмену можно в описании модуля ссылаться на глобальный адрес модуля, так как он более уникален, но в проекте использовать локальный источник. небольшой пример http://vflash.ru/work/zztest/ вот json корневого модуля примера { "modules":{"zzparser": "github:~/vflash/zzparser"}, "scripts": ["./test.js"] } в HTML подключаем его через scmod - http://scmod.vflash.ru/sandbox?src=h...test/test.json на страницу будут подключены три скрипта 1 - [url]http://scmod.vflash.ru/file/3/EasySAXParser/https/raw.github.com/vflash/easysax/master/easysax.js[/url] 2 - [url]http://scmod.vflash.ru/file/2/zzParser,EasySax/https/raw.github.com/vflash/zzparser/master/zzparser.js[/url] 3 - [url]http://scmod.vflash.ru/file/1/module,zzparser/http/vflash.ru/work/zztest/test.js[/url] в данном случаи файлы двух модулей будут загружены из удаленного источника. Оба модуля расположены на github-е отчего загрузка файлов с него значительно медленнее чем могло быть с локального. Также нет возможности делать в них локальные правки. используя подмену можно заменить глобальный адрес локальным. для этого создал папку deps и туда клонировал два репозитория git clone git://github.com/vflash/zzparser.git git clone git://github.com/vflash/easysax.git в этой же папке создал файл со списком подмен http://vflash.ru/work/zztest/deps/replace.json { "replace": { "github:~/vflash/easysax": "./easysax/easysax.json", "github:~/vflash/zzparser": "./zzparser/zzparser.json" } } теперь в HTML подключаем наш модуль с указанием списка подмен http://scmod.vflash.ru/sandbox?rep=d...test/test.json на страницу будут подключены три скрипта, но уже только с локального источника 1 - [url]http://scmod.vflash.ru/file/3/EasySAXParser/http/vflash.ru/work/zztest/deps/easysax/easysax.js[/url] 2 - [url]http://scmod.vflash.ru/file/2/zzParser,EasySax/http/vflash.ru/work/zztest/deps/zzparser/zzparser.js[/url] 3 - [url]http://scmod.vflash.ru/file/1/module,zzparser/http/vflash.ru/work/zztest/test.js[/url] список подмен можно описать не только в отдельном файле но и в корневом модуле, свойство "replace". дополнительно для scmod указываем rep=true - http://scmod.vflash.ru/sandbox?rep=t...test/test.json { "modules":{"zzparser": "github:~/vflash/zzparser"}, "scripts": ["./test.js"], "replace": { "github:~/vflash/easysax": "./deps/easysax/easysax.json", "github:~/vflash/zzparser": "./deps/zzparser/zzparser.json" } } |
добавлен функционал для работы из консоли.
после установки модуля доступны следующие команды Код:
scmod-scripts -3 -lang=en ./side-zzreader/src/zzreader/feedreader.json команда scmod-styles - компилирует все css-стили в один файл команда scmod-langs - формирует список строк для локализации параметр -for=SS задает ключи локализации для команды scmod-langs параметр -lang=SS указывает ключ локализации для команды scmod-scripts параметр -[1..9] задает адрес корневого каталога относительно указанного модуля параметр -max выдача будет без сжатия кода параметр -rep разрешает подмену адресов. матрица должна быть указанна в корневом модуле параметр -rep=./deps/replace.json разрешает подмену адресов. матрица расположена в файле |
зачем 3 команды если всё это можно делать одной? а то и вообще можно делать пересборку при изменении файлов автоматом.
да и всякие "списки подмен" не мешало бы генерить автоматом. есть ли загрузка css если загружен соответствующий js? где сборщик шаблонов? |
Цитата:
консольные команды нужны для публикации. для разработки используется веб-сервис, он формирует sandbox по запросу. Цитата:
Цитата:
сейчас пока только такая модель, для многих проектов этого достаточно. хочу в будущем реализовать и другие модели, но пока обдумываю как лучше делать и какую. Цитата:
|
Зачем так делать? Это же одна операция - сборка ассетов.
Зачем она тогда вообще нужна? о0 Ну это понятно. То есть каждый файл нужно подключать вручную? А все и не надо. Ты же не поддерживаешь всякие cofeescript и sass? Как ты сейчас обходишься с шаблонами? Гвоздями прибиваешь в JS? Грузишь в HTML? Ходишь на сервер чтобы что-нибудь отрендерить? |
подмена нужна чтоб для идентификатора модуля использовать глобальный адрес, но загружать модуль локально. это альтернатива централизованного каталога.
Цитата:
Цитата:
каждый пользуется какими-то своими шаблонизаторами. я не хочу сборщик превращать во фреймворк или комбайн. в крайнем случаи можно компилировать вручную по команде, в модуле просто подключить эти готовые файлы. можно написать какойто автомат который будет компилировать шаблоны по изменению файла. sass и подобное можно былобы всунуть прям в код, благо их не так много. но как сделать красиво у меня идей пока нет. ну и я ими не пользуюсь, хватает возможностей css. |
А зачем указывать глобальный адрес? Чем локальные-то не угодили?
Вручную - это же страшный геморрой. Неужели это никак не автоматизировать? Это не шаблоны, а билдер. Разница в том, что шаблоны являются расширением целевого синтаксиса, а билдер конструирует используя исходный. Ну да не суть. Каждый пользуется какими-то своими [чем угодно], и хороший сборщик должен предоставлять апи в том или ином виде, чтобы к нему можно было прицепить другие приблуды. При этом вовсе не обязательно поддержку их всех реализовывать. Но хотя бы один пример крайне желателен. Для примера, мой сборщик состоит из ядра, которое реализует единую схему разруливания зависимостей. И пачку модулей для сборки различных ассетов: для веб скриптов, для нодных скриптов, для расширений для мозиллы, для расширений для хрома, для стилей, для стилей с использованием sass, для xslt-шаблонов, для smatry-шаблонов, для локалей, для png-спрайтов, для svg-спрайтов... всё что им нужно - используя ядро получить отсортированный список файлов и слить их воедино. Для нового типа ассетов сборщик пишется на раз-два. Да, ещё пачка модулей для различных форматов файлов - чтобы зависимости искать автоматически, а не забивать их ручками. |
Цитата:
Цитата:
Цитата:
я не пытаюсь создать кухонный комбайн. мне хватает того функционала который есть сейчас. делать фичи которыми не буду пользоваться плохая практика разработки инструментов. |
В чём проблема переименовать один из них, раз уж сразу мы не позаботились использовать вендорные префиксы?
Есть разные способы. Например, у меня анализируются xslt шаблоны и подключаются только те модули, что реально используются. Вообще я вроде рассказывал. Но я так понимаю критика и свежие идеи тебя не интересуют. Ок. Знаешь, попробовав лучшее, на такие велосипеды уже не смотришь) |
Цитата:
Цитата:
Цитата:
|
А без префиксов получаем кашу. В разных местах под одним именем скрываются совершенно разные сущности.
Отличается тем, что я делаю это один раз - по факту использования. А ты в двух местах: там где подключаешь и там где используешь. Я был бы счастлив, если бы мне не приходилось писать самому столь базовые вещи. |
Цитата:
структура описана только в json файле. в одном модуле может быть множество js файлов, но зависимости опишу только один рас в одном месте. |
Когда ты пишешь в файле:
var button = new My.Component('button') То неявно объявляешь зависимость от модуля My.Component Этот код зависит от этого модуля и если он не будет предварительно подключен, то код выдаст ошибку. И все такие зависимости ты дублируешь в json-описании. |
релиз v0.2.10
Реализовал еще один вариант сборки. Идея такая - собирать проект не в один js(css) файл, а в два. Первый файл это ядро и оно общее на всех страницах. Второй это код только для определенной странице. Выглядит примерно это так: 1) собираем модуль-ядра http://scmod.vflash.ru/sandbox?src=h...s/replace.json 2) собираем модуль-страницы исключив из него модули-ядра . (параметр &core=[url]) http://scmod.vflash.ru/sandbox?src=h...ore/zcore.json На страницу подключаем оба результата |
Поздравляю. Ещё немного и вы переизобретёте недо-YUI :)
А чем вам require.js не угодил ? |
у YUI другая архитектура.
Цитата:
вот к пример сайт http://www.sochi2014.com/ , эталон . куча js и css файлов подключены сами по себе, без каких либо зависимостей. Переписывать это дело на AMD гиблое дело, проще всех нах.. послать и уволиться. с scmod все просто. собираем js и css в списочек, и первый шаг к грамотной организации файлов сделан. { "nowrap": true, "script": [ "/Content/js/lib/head.min.js" , "/Content/js/lib/modernizr.js" , "/Content/js/lib/jquery.js" , "/Content/js/lib/json.js" , "/Content/js/lib/jquery.jscrollpane.js" , "/Content/js/lib/jquery.fader.js" , "/Content/js/util.js" , "/Content/js/articul/tools.js" , "/Content/js/storejs/store_json2.min.js" , "/Content/js/adriver/adriver.core.2.js" , "/Content/js/articul/announce.js?t=635047491833716637" , "/bitrix/components2/Articul.Sochi.Components/QuoteBlockHomepageComponent/templates/.default/script.js?t=635029161642020053" , "/bitrix/components2/Articul.Sochi.Objects/MapHomepageComponent/templates/.default/script.js?t=634964358382536565" , "/Content/js/articul/event-scroller.js?t=635095805248728492" , "/Content/js/lib/jquery.mousewheel.js?t=635025631538839519" , "/bitrix/components2/Articul.Sochi.Twitter/TweetListComponent/templates/.default/script.js?t=635013476703264764" , "/Content/js/articul/blogs.js?t=635023237566266204" , "/Content/js/articul/polls.js?t=635029161638739013" , "/bitrix/components2/Articul.Sochi.Components/InterestingBlockHomepageComponent/templates/.default/script.js?t=635029161641893108" , "/Content/js/articul/partners-banners.js?t=635029161638729248" ], "styles": [ "/Content/css/main.css" ,"/Content/css/articul/pit.css" ,"/Content/css/mm.css" ,"/Content/css/index.css" ] } |
Почему у YUI другая архитектура ?
Я объявляю модуль, он находится в своей песочнице. Могу экспортировать из него нужные мне объекты в глобальное окружение. Указываю от каких модулей зависит текущий и модули будут сами подгружены. Могу указать, что у модуля есть css и тогда css будет подгружена. Могу указать что модуль мультиязычный и язык сам будет определён и подгружен, если существует такой языковой файл. Плюс я могу получить все модули одним файлом в одном запросе. |
Madzi,
если сравнивать камаз и жигули, то да. и тот и этот автомобиль. у YUI больше с AMD общего |
Не улавливаю аналогии.
Исходная задача - структурировать файлы (при разработке больших проектов). И в этом направлении я и сравниваю... |
YUI,AMD - на клиенте
scmod - веб сервис YUI,AMD - асинхронное подключение js файлов (разработка) scmod - не асинхронное подключение js файлов (разработка) YUI,AMD - один модуль , один js файл scmod - один модуль , сколь угодно js файлов YUI,AMD - область видимости кодишь сам scmod - область видимости делает автоматом весь файл YUI,AMD - строгий режим нужно выставлять самому scmod - строгий режим делает автоматом YUI,AMD - подключить старый код без доработки нельзя scmod - подключить старый код без доработки можно YUI,AMD - собирать проект в два файла не умеет scmod - собирать проект в два файла умеет |
Какие-то у вас не правильные сведения :)
Цитата:
У Yahoo ещё на его базе проект Mojito есть, когда сервер сам распределяет код, который будет выполняться на нём и на клиенте. На слабых клиентах - мало кода (основной код выполняется на сервере) и наоборот. Цитата:
Цитата:
Цитата:
// Модуль YUI YUI.add('test', function (Y) { //... песочница, ограничивающая код }); Цитата:
Цитата:
Цитата:
|
> Строгий режим по-умолчанию стоит в компрессоре (yuicompressor), который сжимает скрипты перед продакшеном (обычно используют *-min.js файлы).
При разработке код должен быть максимально приближен к боевому с точностью до эквивалентных преобразований (например, безопасная минификация). Включать стрикт режим только для релиза - всё равно что ходить с заряженным пистолетом у виска |
Цитата:
YUI.add('test', function (Y) { 'use strict' //... код ... }); Просто иногда попадается legacy код, на который легче закрыть глаза (отключить strict), чем переписать его. Поэтому опоциональность скорее плюс, чем минус. |
Цитата:
'use strict' частенько забывал добавить в код. а потом долгие поиски где что не работает. Отсюда и решение чтоб он по умолчанию всегда был включен. опционально также могу и выключить имхо наш диалог путь в некуда. У меня не достаточно познаний в библиотеке YUI чтоб объективно вести диалог по поводу этой библиотеке. Судить могу только по примерам, которые мне сильно напоминают AMD. Код AMD я изучал и ничего кроме костылей я там не увидел. Асинхронная природа и необходимость ручного оборачивания модуля считаю критичной причиной не рассматривать AMD для проектов. |
Цитата:
|
vFlash.
А мне нравится ход твоих мыслей :) Я примерно к похожим выводам приходил. Но вот только для девелоперской версии, одним файлом отдавать не надо, так как отлаживать большой файл неудобно. Тем более его не стоит сжимать. А вот в продакшене как раз одним сжатым файлом надо, и желательно сжатым предварительно. в общем по одному описанию приложения должно собираться в двух вариантах, чтобы я добавил файл в описание и он и в продакшене будет и в девелоперской версии. Что то вроде компилятора для продакшена (возможно на базе grunt) , и для девелоперов какой то загрузчик на клиенте который умеет забирать файлы описанные в json. Как то так я себе это вижу. |
DjDiablo,
есть три основные команды sandbox, scripts, styles sandbox как рас и есть дивелоперская версия. это небольшой js файл который использует document.write для вставки всех js и css с заранее подготовленной последовательностью. js при этом подключаются не на прямую а через специальное прокси которое немного модифицирует файл, но сохраняет положение строк как у оригинала. document.write('...') нужен чтоб с одной стороны все было синхронно, с другой чтоб загрузка была в несколько потоков. вот sandbox http://scmod.vflash.ru/sandbox?src=h...s/replace.json вот пример как выглядит js-файл после прокси http://scmod.vflash.ru/file/6jyfv5/m...cram_notify.js |
Часовой пояс GMT +3, время: 18:06. |