Catalog npm
PACKAGE EXPLORERView in registry

2mqjs

npm

A tiny performance-first architecture toolkit for framework-free web apps: lazy components, event ports, workers, tasks, and an off-main-thread store.

event-busfrontend-architecturelazy-loadingstate-managementtypescriptvanilla-jsweb-performanceweb-workers
Versions collected11
Direct dependencies4From release 0.1.6
Last observed20 Oct, 19:15 UTC

README

Current package documentation

2mqjs

2mqjs logo

npm version CI CodeQL install size TypeScript strict MIT license

Маленький performance-first архитектурный набор для веб-приложений без фреймворков.

English version · Components · Ports · Workers · Tasks · Store · Events


Что это?

2mqjs помогает разбить vanilla TypeScript/JavaScript сайт на небольшие runtime-слои:

  • UI-компоненты загружаются только тогда, когда они реально нужны.
  • Бизнес-логика может уехать в Web Workers.
  • События идут через явные ports, а не через скрытые связи между модулями.
  • Tasks управляют порядком запуска, видимостью, idle-временем, готовностью данных и воркеров.
  • Store может жить вне main thread и сохраняться между перезагрузками.

Библиотека нужна для страниц, где важны маленький initial JS, меньше работы в main thread и предсказуемый порядок инициализации.

Установка

npm i 2mqjs
# или
pnpm add 2mqjs
# или
yarn add 2mqjs

Проект должен использовать ESM:

{
  "type": "module"
}

Импортируйте только нужное

2mqjs публикует subpath exports, чтобы bundler мог не тянуть лишнее:

import { registerComponent } from '2mqjs/components';
import { emitPort, onPort } from '2mqjs/ports';
import { registerTask } from '2mqjs/tasks';

Корневой экспорт тоже доступен, если удобнее:

import { registerComponent, emitPort, registerTask } from '2mqjs';

Быстрый старт

1. Ленивые UI-компоненты

import { registerComponent, runComponentLoader } from '2mqjs/components';

registerComponent({
  name: 'product-card',
  load: () => import('./components/product-card.js'),
  when: 'visible',
  hasDisplay: true,
});

runComponentLoader();
<article data-component="product-card"></article>

Модуль компонента:

export function display(el: Element) {
  el.innerHTML = '<button data-add>Добавить в корзину</button>';
}

export function boot(el: Element) {
  el.querySelector('[data-add]')?.addEventListener('click', () => {
    // Тяжёлая логика стартует только после появления компонента.
  });
}

2. Ports: явные события приложения

import { emitPort, onPort } from '2mqjs/ports';

const off = onPort<{ id: string }>('cart:add', ({ id }) => {
  console.log('Добавить товар', id);
});

emitPort('cart:add', { id: 'sku-42' });
off();

3. Tasks: предсказуемый порядок запуска

import { registerTask, runTasks } from '2mqjs/tasks';

registerTask({
  id: 'hydrate-products',
  stage: 'bootstrap',
  when: 'idle',
  run: async () => {
    // Некритичная работа ждёт idle-времени.
  },
});

await runTasks('bootstrap');

4. Workers: тяжёлая логика вне main thread

import { registerWorker, emitPort } from '2mqjs/workers';

await registerWorker({
  name: 'productData',
  src: () => import('./workers/productData.worker.js'),
});

emitPort('productData:init', { page: 'catalog' });

5. Store: состояние в dedicated worker

import { defineGlobalStore } from '2mqjs/store';

const app = defineGlobalStore({
  name: 'shop',
  initial: { cart: [] as string[] },
  persist: ['cart'],
});

await app.ready;

app.watch('cart', cart => {
  console.log('Корзина изменилась', cart);
});

app.add('cart', 'sku-42');

Модули

МодульДля чегоИмпорт
ComponentsЛенивые UI-модули, display/boot, запуск по видимости и взаимодействию2mqjs/components
PortsЛёгкий pub/sub со snapshot/replay2mqjs/ports
WorkersРегистрация воркеров и port-based messaging2mqjs/workers
TasksОркестрация запуска, зависимости и runtime-условия2mqjs/tasks
StoreГлобальное состояние вне main thread + persist2mqjs/store
EventsDOM-утилиты: делегирование событий и resize subscriptions2mqjs/events

Принципы runtime

  • Откладывать по умолчанию. Запускать дорогой UI и логику только когда они нужны.
  • Держать слои явными. UI, данные, воркеры и orchestration общаются через маленькие контракты.
  • Не привязывать к фреймворку. Можно использовать рядом с SSR, islands, виджетами или обычным HTML.
  • Следить за размером. Subpath exports и release smoke checks защищают package shape и bundle budgets.

Текущий roadmap

Следующий цикл разработки сфокусирован на production-grade производительности:

  • lazy components без потери первого interaction;
  • shared observers и cache в component loader;
  • cleanup жизненного цикла listeners в ports/tasks/events/workers;
  • patch-based store updates вместо отправки всего state;
  • SharedWorker mode для синхронизации стора между вкладками;
  • улучшение scheduler: DAG validation, cancellation, timeouts, concurrency limits;
  • browser smoke tests, benchmarks и bundle-size budgets.

Подробный backlog — в open issues.

Релизы

2mqjs теперь использует GitHub automation:

  • CI гоняет release gate на поддерживаемых версиях Node.js.
  • CodeQL сканирует JavaScript/TypeScript код.
  • Dependabot группирует обновления npm и GitHub Actions.
  • Release Please создаёт release PR из Conventional Commits.
  • npm-публикация идёт через GitHub Actions с provenance.

Локальная проверка перед релизом:

npm run release:check

Лицензия

MIT

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 11

Collected releases
VersionPublishedDirect dependenciesOpen version
0.1.6Registry latest11 Aug 20264
0.1.529 Jul 20264
0.1.428 Jul 20264
0.1.323 Jul 20264
0.1.223 Jul 20264
0.1.129 Jun 20261
0.1.029 Jun 20261
0.0.414 Aug 20254
0.0.314 Aug 20254
0.0.214 Aug 20254
0.0.114 Aug 20254

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Repository

PENDING
poliklot/2mqjs

Shared repository data · GitHub

License detected in repository
Not collected

Repository

PENDING
your-org/2mqjs

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 19:15 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:0d3495a27ce629d8cae1f3e6eda8e403bbcad77456be70456ccb7d6fd9d4cddb