moonjs

Ten years ago, I was one of the judges in an Open Source award competition, In the JavaScript competition I remember jQuery won the JavaScript category. If today we ran again the same competition it will be really hard to decide which JavaScript library is today the best, as the competition is getting bigger and performance of the libraries are getting much much higher.

In this context, we will talk today about MoonJs a fast, tiny, and intuitive Javascript library which you can use packed in 2KB (minified+gziped) with a blazingly fast view rendering performance, and a purely functional driver-based design.

Applications today are complex, built on top of frameworks that create abstractions fundamentally based on mutability and imperative code. They introduce concepts like reactivity or local state or algebraic effects, all in attempt to represent views as a function of state. In reality, applications are much more sophisticated and require third-party libraries for any effects other than updating a view.

Moon is a novel approach to web applications based on pure functions. An application is a function that uses drivers, programs that provide an interface to the real world. These functions take input from drivers and return output to drivers. Drivers can be responsible for things like views, state, audio, HTTP requests, routing, and timing events. Applications run on the Moon, and drivers update the Earth.

Functional and declarative

const button = Moon.view.m.button;

const increment = ({ data }) => {
	const dataNew = data + 1;

	return {
		data: dataNew,
		view: <view data=dataNew/>
	};
};

const view = ({ data }) =>
	<button @click=increment>{data}</button>;

Moon.use({
	data: Moon.data.driver,
	view: Moon.view.driver("#root")
});

Moon.run(() => ({
	data: 0,
	view: <view data=0/>
}));

In Moon, web applications are treated as functions that take driver inputs and return driver outputs. Drivers handle the interface between the output of your application and the browser so that it can stay pure and declarative.

On the contrary, other popular frameworks claim to be “declarative” but only treat the view as a function of state. However, they treat other ideas such as local component state or effects as afterthoughts, requiring imperative and impure code.

Tiny & Fast

Modern web frameworks often add a lot of weight to JavaScript bundles, resulting in slower web applications and load times. This effect is especially visible when using a slow internet connection.

Since Moon is so simple at its core, where it creates an abstraction to allow drivers to handle input and output, it only weighs 2kb minified and gzipped. On top of that, it is specifically optimized for JavaScript engines to perform fast virtual DOM diffing and DOM operations.

You can check yourself MoonJs interactive benchmark, the preliminary results are impressive. Official results are listed here for different chrome versions.

Intuitive & Consistent

Moon has a very minimal API surface, used solely for initializing a runtime that allows for functional applications inside the imperative browser environment. The view language was designed to mimic HTML, a language familiar to most web developers.

Other view languages often have variadic arguments that can have any type for creating view nodes. They create abstractions like directives or special template syntax for control flow. Moon’s view language is consistent, where every tag is a function call and control flow is normal JavaScript.

// Moon view
const posts = (
	<div children=(posts.map(post =>
		<view.post id="my-post">{post}</view.post>
	))/>
);

// Compiled to JS
const posts = (
	div({
		children: posts.map(post =>
			view.post({
				id: "my-post",
				children: [Moon.view.m.text({data: post})]
			})
		)
	})
);

Getting Started

Moon can be installed directly from the browser or from npm using :

npm i moon-cli -g

Then you can create your first moon project using :

moon create moon-prj

If you want to use Moon directly from your browser you can include the libraries Moon and Moon-Browser :

<script src="https://unpkg.com/moon"></script>
<script src="https://unpkg.com/moon-browser"></script>

And then you can run moon script inside your page using the type text/moon :

<!-- As an external script -->
<script src="moon.script.js" type="text/moon"></script>
<!-- As an inline script -->
<script type="text/moon">
    ...
</script>

Now first thing to do is adding the root, the single element where the Moon app is mounted, and we usually use the div element :

<div id="root"></div>

This is a root element where Moon’s view driver will mount the view. Begin the script by importing the HTML elements from Moon’s view driver that will be used in the view. A script can be added to a JavaScript file linked to the HTML page or a script tag.

const { div, h1, ul, li, input, button } = Moon.view.m;

After initializing the application, add the following to the script to display a basic todo list view

const viewTodos = ({ data }) =>
    <ul children=(data.todos.map(todo =>
        <li>{todo}</li>
    ))/>;

Moon.use({
    data: Moon.data.driver,
    view: Moon.view.driver("#root")
});

Moon.run(() => {
    const data = {
        todo: "",
        todos: [
            "Learn Moon",
            "Take a nap",
            "Go Shopping"
        ]
    };

    return {
        data,
        view: <viewTodos data=data/>
    };
});

This will give you a simple todo list, and you can follow the guide to see how to play with data and make it more interactive. Moon is free and open source, released under an MIT license. for more information https://moonjs.org/

LEAVE A REPLY

Please enter your comment!
Please enter your name here