Capa do post

Conhecendo o Nullstack, um framework brasileiro

3/14/2022

O Nullstack é um framework web para construção de PWAs — Progressive Web App — que conecta duas camadas em um mesmo componente, por assim dizer, podemos escrever a parte de UI — User Interface —, gestão de estados e ainda o backend, fazendo uso de microsserviços especializados.

Os componentes Nullstack são simplesmente classes Javascript assim como em React, tendo de diferencial a mobilidade de escrever não só o frontend, mas também o backend no mesmo componente.

Tendo isso em mente, vamos ver um exemplo de componente que pega uma waifu e renderiza ou simplesmente dá erro 404:

import Nullstack from "nullstack";

class MyWaifuPage extends Nullstack {
  name = "";
  biography = "";

  static async findWaifuByName({ database, name }) {
    return await database
      .collection("waifus")
      .findOne({ name });
  }

  async initiate({ page, params }) {
    const waifu = await this.findWaifuByName({
      name: params.name,
    });

    if (waifu) {
      page.title = waifu.name;

      Object.assign(this, waifu);
    } else {
      page.status = 404;
    }
  }

  render() {
    return (
      <section>
        <h1>{this.name}</h1>
        <img src={this.src} alt={this.name} title={this.name} />
        <div>{this.biography}</div>
      </section>
    );
  }
}

export default MyWaifuPage;

Neste exemplo temos a função findWaifuByName que enquanto o Nullstack estiver renderizando em Server Side, será chamada normalmente, mas em Client Side vai ser transformada em um microsserviço especializado.

Em componentes Nullstack, initiate é um método de ciclo de vida que quase sempre vai estar presente. Podendo ser tanto síncrono quanto assíncrono; você pode usá-lo para invocar outra função do servidor e carregar os dados para apresentar na página.

Lembrete: Funções de servidor são, por via de regra, métodos declarados com static async.

Como o Nullstack lida com o back e front

Por baixo dos panos com ajuda da própria extensão de arquivos, o Nullstack gera dois pacotes, um para o servidor, e outro do cliente, contendo o mínimo possível de dependências

Em tempo de execução, o próprio framework decide qual pacote usar, se deve chamar uma função local ou invocá-las por meio de API, ficando à cargo do programador apenas a lógica e regras de negócio.

O Nullstack promete ser e também é um framework poderoso de fácil escalabilidade, altamente flexível e de fácil refatoração, se necessário.

Tendo em sua essencia a simplicidade e escalabilidade, em cada ambiente de serviço o Nullstack traz um objeto context, que é um proxy passado para cada função.

Objeto context

Vamos ver sobre este objeto:

import Nullstack from "nullstack";
import { readFileSync } from "fs";
import { Remarkable } from "remarkable";

class About extends Nullstack {
  static async start(context) {
    const text = readFileSync("README.md", "utf-8");
    const md = new Remarkable();

    context.readme = md.render(text);
  }

  static async getReadme({ readme }) {
    return readme;
  }

  async initiate(context) {
    if (!context.readme) {
      context.readme = await this.getReadme();
    }
  }

  render({ readme }) {
    return <article html={readme || ""} />;
  }
}

export default About;

Aqui temos o método start inicializando nosso componente e já adicionando a key readme ao nosso contexto. Este é um método que será chamado apenas no servidor, não estando disponível no client.

Vamos ter também o método getReadme, que será transformado em endpoint a ser chamado no cliente, e neste caso apenas retorna a key do contexto de servidor.

No nosso initiate, verificamos se a key existe no nosso objeto, se não, criamos e atribuímos o retornado de getReadme.

Mas porque vamos verificar se existe, sendo que adicionamos ainda no método start?

Simples. Porque o initiate pode ser chamado tanto no lado do cliente quanto do lado do servidor, e o método start ele é um método de servidor

Se o usuário está acessando nossa página e não ta vindo de outra página do nosso projeto, ou seja, é a primeira visita dele, o contexto passado pra initiate já vai ter a key que precisamos, mas caso já venha de outra página na nossa aplicação, o Nullstack vai chamar nosso microsserviço getReadme que criamos como função de servidor.

Pra não restar dúvidas: initiate é um dos métodos internos Nullstack que o framework sempre vai chamar quando estiver montando o componente, estando presente tanto no pacote do client quanto do server.

Opa, meio grandinho, né? Falaremos mais sobre Nullstack em outra oportunidade.

Não esqueçam de passar no repositório GitHub do projeto e dar uma estrelinha pra ajudar este incrível projeto que é totalmente BR.

Leia também:

Onde me encontrar