my-framework-almaz: A Learning Framework

2.0.7 · maintenance · verified Tue Apr 21

my-framework-almaz (npm package `my-framework-almaz`, current stable version 2.0.7) is an educational frontend framework explicitly designed as a companion to the book "Build a frontend framework from scratch." Its primary purpose is to teach web developers the underlying mechanics of modern frontend frameworks, rather than for production application development. The framework evolves through different versions, mirroring chapters of the book, introducing core concepts like the Virtual DOM, implemented via `h()`, `hString()`, and `hFragment()` functions, and DOM manipulation functions such as `mountDOM()` and `destroyDOM()`. Early versions (like v1.0) utilized a simple state management pattern with a `Dispatcher` where any state change triggered a complete re-rendering of the entire view. Subsequent versions, starting from v2.0 (as indicated by the introduction of a 'reconciliation algorithm'), move towards more efficient partial DOM updates. Due to its pedagogical nature, it lacks the optimizations, security considerations, and robust feature set expected in production-grade frameworks. Its release cadence is likely tied to book updates and chapters.

Common errors

Warnings

Install

Imports

Quickstart

This example demonstrates how to create a simple interactive application using `createApp`, `h` for Virtual DOM creation, `mountDOM` for rendering, and the `Dispatcher` for state management. It illustrates an initial render and subsequent full re-renders (characteristic of v1.0) when state changes via dispatched commands.

import { createApp, h, mountDOM, Dispatcher } from 'my-framework-almaz';

interface State {
  message: string;
  count: number;
}

const initialState: State = {
  message: 'Hello, my-framework-almaz!',
  count: 0,
};

let appState = { ...initialState };
const dispatcher = new Dispatcher();

const UPDATE_MESSAGE = 'UPDATE_MESSAGE';
const INCREMENT_COUNT = 'INCREMENT_COUNT';

dispatcher.subscribe(UPDATE_MESSAGE, (payload: string) => {
  appState.message = payload;
});

dispatcher.subscribe(INCREMENT_COUNT, () => {
  appState.count++;
});

function renderApp() {
  return h('div', { id: 'my-app' }, [
    h('h1', {}, appState.message),
    h('p', {}, `Count: ${appState.count}`),
    h('button', {
      onclick: () => {
        dispatcher.dispatch(INCREMENT_COUNT);
        updateView();
      },
    }, 'Increment Count'),
    h('button', {
      onclick: () => {
        dispatcher.dispatch(UPDATE_MESSAGE, 'Updated message from command!');
        updateView();
      },
    }, 'Update Message'),
  ]);
}

const app = createApp(renderApp);

function updateView() {
  const rootElement = document.getElementById('app-root');
  if (rootElement) {
    while (rootElement.firstChild) {
      rootElement.removeChild(rootElement.firstChild);
    }
    mountDOM(app.render(), rootElement);
  }
}

document.addEventListener('DOMContentLoaded', () => {
  const root = document.createElement('div');
  root.id = 'app-root';
  document.body.appendChild(root);
  updateView();
});

view raw JSON →