DEV Community

Jay Landrum
Jay Landrum

Posted on

Rolling my own front-end framework pt. 1/?

For a long time I've iterated on my own small front-end framework fueled by ongoing developer gripes with popular libraries. My goal here is to write a series of posts as a retrospective on that work, summarize design goals and document the problems I faced and how I chose to solve them.

Repo link: j-templates

The framework was used to make Qwiqwit, a multi-player web-game I built with my friend, Paul.

Some of the initial goals were:

  • No transpile step besides TypeScript
  • Fully typed in the editor, no bindings in string or .html templates
  • Sensibly reactive, no need to self-manage change detection

My goals were reactions to pitfalls present in early React/Angular development. This was 6+ years ago so a lot of these complaints have been addressed since.

Hello World

import { Component } from 'j-templates';
import { div } from 'j-templates/DOM';

// Create the Component class
class HelloWorld extends Component {

    // Override the Template function
    Template() {
        return div({}, () => "Hello world");
    }

}

// Convert the class to an element function
const helloWorld = Component.ToFunction("hello-world", null, HelloWorld);
// Append a new hello-world element to the page
Component.Attach(document.body, helloWorld({}));
Enter fullscreen mode Exit fullscreen mode

Produces the following markup:

<hello-world>
    <div>Hello world</div>
</hello-world>
Enter fullscreen mode Exit fullscreen mode

All elements are represented as functions that take a configuration object. The HelloWorld component class is converted to a function using the Component.ToFunction(...) method. Calling one of these function returns a NodeDefinition object which is the framework's virtual representation of the DOM.

Element functions (i.e. div, span, p) take a second parameter to define children. This function can return a string to create a text node or one/many NodeDefinition objects. This is all you need to start building static views.

import { Component } from 'j-templates';
import { div, span, h1, b } from 'j-templates/DOM';

class MessageHeader extends Component {
    Template() {
        return h1({}, () => "Incoming Message");
    }
}

const messageHeader = Component.ToFunction("message-header", null, MessageHeader);

class HelloWorld extends Component {
    Template() {
        return [
            messageHeader({}),
            div({}, () => [
                b({}, () => "Message Body: "),
                span({}, () => "Hello world")
            ])
        ];
    }
}

const helloWorld = Component.ToFunction("hello-world", null, HelloWorld);
Component.Attach(document.body, helloWorld({}));
Enter fullscreen mode Exit fullscreen mode

Produces the following markup:

<hello-world>
    <message-header><h1>Incoming Message</h1></message-header>
    <div><b>Message Body: </b><span>Hello world</span></div>
</hello-world>
Enter fullscreen mode Exit fullscreen mode

Give it a shot: Code Sandbox. Next post will describe how to bind to data.

Sentry blog image

How I fixed 20 seconds of lag for every user in just 20 minutes.

Our AI agent was running 10-20 seconds slower than it should, impacting both our own developers and our early adopters. See how I used Sentry Profiling to fix it in record time.

Read more

Top comments (0)

SurveyJS custom survey software

Build Your Own Forms without Manual Coding

SurveyJS UI libraries let you build a JSON-based form management system that integrates with any backend, giving you full control over your data with no user limits. Includes support for custom question types, skip logic, an integrated CSS editor, PDF export, real-time analytics, and more.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay