DEV Community

Jhony Walker
Jhony Walker

Posted on

Remix - 6 recursos matadores

Remix

Principais destaques de uma estrutura JavaScript full-stack revolucionária, o ecossistema da web React nunca pareceu melhor.

Em 2021, vimos como foi o grande lançamento da versão Next.js 12, e ele trouxe recursos incríveis como o compilador baseado em SWC Rust, middleware, suporte para React 18 e importações de URL. Quando pensamos que o ano acabou, acabamos de receber o último lançamento do Remix. Ele mudou para ser um framework full-stack gratuito e de código aberto. Eles embarcaram recentemente no Kent C. Dodds. Quem é ele? O criador do React Testing Library. Uma biblioteca de testes tão incrível que mudou a maneira como testamos nossos componentes React hoje em dia. Ele reescreveu todo o seu blog em Remix desde então.

De repente, escolher um framework ficou mais difícil. Isso não é uma má notícia, porém, temos outro ótimo framework full-stack a considerar ao iniciar um novo projeto. Neste artigo, veremos os recursos que tornam esse framework tão incrível e por que você deve considerá-lo para seu próximo projeto:

1º) Fácil Instalação

Um framework deve ser sempre fácil de instalar e começar, isso aumenta sua adoção e o Remix se enquadra nessa posição. Ele vem com uma configuração intuitiva, tudo o que precisamos fazer para começar é executar o comando abaixo:

npx create-remix@latest
Enter fullscreen mode Exit fullscreen mode

Teremos que responder a duas perguntas:

A primeira é sobre onde queremos hospedar nosso aplicativo: aRemix App Server, Express Server, AWS Lambda, Fly.io, Netlify, Vercel ou Cloudflare Pages porém podemos facilmente mudar isso depois.

Em seguida, devemos definir se queremos que nosso projeto seja baseado em JavaScript ou Typescript.

E é isso, assim estamos todos preparados, em menos de 1 minuto estamos todos prontos para ir. A execução do nosso projeto é bastante fácil. Há um monte de tarefas yarn/npm que podemos usar. Vamos ver como podemos pular direto para o modo de desenvolvimento:

// após a configuração 
$ cd [o nome do projeto] 
$ npm install ou yarn install 
$ npm run dev ou yarn run dev
Enter fullscreen mode Exit fullscreen mode

Alternativamente, ainda podemos fazer uma instalação manual. Nós só temos que instalar as dependências e adicionar alguns arquivos de configuração. É menos conveniente, mas factível.

2º) Melhoria progressiva

JavaScript nos capacita a construir sites mais rápidos e eficientes isso torna possível o paradigma de aplicação de uma página única. No entanto, o JavaScript ainda pode ser desativado, normalmente isso tende a quebrar a página inteira, porém com o Remix isso não vai acontecer. O único efeito colateral será que a experiência interativa é rebaixada. Como isso exatamente? Principalmente confiando na linguagem padrão do navegador, como formulários e links.

Precisamos construir nosso aplicativo de uma maneira específica para ter esse suporte de aprimoramento progressivo?

Sim, teremos que abraçar a abordagem opinativa do Remix.

A estrutura Remix está aproveitando a computação para o servidor o máximo possível. O comportamento padrão do Remix é executar a renderização do lado do servidor. Portanto, quando o JavaScript não estiver disponível, nossos usuários não receberão uma página em branco eles obterão a mesma página HTML, mas com experiência em HTML bruto. A página não será hidratada, pois nenhum JavaScript será executado.

O que acontece com recursos interativos como formulários e roteamento?

Quando o JavaScript está disponível, ele aprimora os recursos impedindo o comportamento padrão do navegador. Quando estiver desabilitado, o comportamento bruto do navegador será usado. Veremos isso mais detalhadamente nos recursos de formulário, roteamento e carregamento de dados, isso torna o JavaScript um recurso mais do que um requisito e desativá-lo apenas piora a experiência do usuário.

3º) Carregamento de dados

Esta é uma característica legal. Normalmente o que fazemos é carregar a rota e depois carregar os dados em um hook useEffect(..., []). A abordagem do Remix é diferente, em vez disso, ele procurará um arquivo exportado da função loader no módulo de página raiz. Se disponível, ele o executará no servidor e passará seus resultados para o navegador.

Podemos buscar esses dados de qualquer lugar: JSON, API, banco de dados... Nós temos acesso aos parâmetros do caminho. Quão? Eles estão disponíveis como um argumento da função loader.

Como podemos torná-los seguros para o tipo?

O objeto params é um chave-valor de string e união string | undefined. Nós apenas temos que afirmar que o parâmetro não é nulo podemos usar a tiny-invariant biblioteca para esse fim:

import invariant from "tiny-invariant";
export const Loader: LoaderFunction = async ({params}) => {
  ...
  // ✅ se o params estiver ausente, disparará um erro
  invariant(params.id, "Expected id Parameter");
  ...
Enter fullscreen mode Exit fullscreen mode

Vamos ver um exemplo completo de uma função loader de exemplo para uma /posts/${id} página:

// file: app/routes/posts/$id.js

import type { LoaderFunction } from "remix";
import invariant from "tiny-invariant";

...

// ✅ função de loader exportada da página
export const loader: LoaderFunction = async ({ params }) => {
  // ✅ falhará se params.id for nulo
  invariant(params.id, "Expected id Parameter");
  // ✅ fetch API está disponível em FE e BE
  const res = fetch(`https://example.com/api/posts/${params.id}`);

  // ✅ retornando os resultados
  return await (
    await res
  ).json;
};

...
Enter fullscreen mode Exit fullscreen mode

No código acima, expusemos os dados para o cliente. Como podemos acessá-lo lá? Por meio de um gancho personalizado fornecido:

import { useLoaderData } de "remix";
export função padrão PostDetails() { 
    let post = useLoaderData (); 
... 
}
Enter fullscreen mode Exit fullscreen mode

As estruturas Remix fornecem tudo o que precisamos para fornecer uma experiência de carregamento de dados do usuário extremamente rápida.

Quando os dados serão recarregados?

As estruturas do Remix cobrem isso atualizando os carregadores no envio de formulários e outros casos de uso. Podemos optar por sair e gerenciá-lo nós mesmos com o manipulador unstable_shouldReload.

Formulários Integrados

Esta é uma característica chocante no início, os formulários existiam muito antes do JavaScript e o Remix está adotando esse comportamento bruto. Eram apenas POST solicitações que estavam redirecionando para uma ação usando o método action ou usando a mesma rota quando ausente.

Quando o JavaScript estiver habilitado, o envio do formulário será desabilitado usando event.preventDefault() e tudo acontecerá através do AJAX. O Formulário será serializado e processado no servidor, os dados serão então devolvidos ao cliente. Podemos realizar operações como redirect também.

Toda a validação do formulário será tratada no servidor, no Remix, se houver algum erro, é uma boa prática retornar um objeto
errors de valor-chave.

Como o Remix lidará com os envios de formulários POST?

Precisamos expor uma função action na página root do formulário.

// ✅ exportando ação da página
export const action: ActionFunction = async ({ request }) => {
  const formData = await request.formData();

  const title = formData.get("title");
  const slug = formData.get("slug");
  const markdown = formData.get("markdown");

  // ✅ se der algum erro irá retornar
  if (title & typeof title !== "string" || typeof slug !== "string") {
    return {
      errors: {
        general: "please fill all forms",
      },
    };
  }

  const { id } = createPost({ title, slug });
  // ✅ redireciona na entidade criada
  return redirect(`/new/${id}`);
}
Enter fullscreen mode Exit fullscreen mode

O acima é tudo o que precisamos fazer no lado do servidor para lidar com envios de formulários. Quais APIs temos no lado do cliente?

  • useSubmit: retorna a função para enviar o formulário programaticamente.
  • useTransition: ele nos diz tudo o que precisamos saber sobre o estado do envio do formulário. Podemos exibir estados de carregamento, desabilitar o envio de formulários, atualizações otimistas... etc, tudo pronto para uso.
  • useFormAction: resolvendo o nome do <form action> usando os caminhos relativos do React Router.
  • useActionData: retorna os dados do formulário enviado. É a maneira preferida de passar erros do servidor de volta para o cliente web.

Quando o JavaScript estiver desabilitado, o formulário será enviado da forma tradicional. O Browser sabe como serializar e enviar um formulário. O Formulário continuará a ser executado e o action ainda será executado na submissão. Obviamente, as APIs JavaScript acima não serão executadas no Client.

5º) Roteamento Integrado

Assim como o Next.js, o framework Remix tem uma maneira opinativa de fazer roteamento. Permite roteamento aninhado. No entanto, o Remix é construído em cima do React Router v6 é uma das bibliotecas de roteadores React mais populares e podemos acessar suas APIs e componentes através do remix. Isso significa que podemos usar nossas APIs react-router v6 favoritas:

  • Outlet: espaço reservado para páginas aninhadas.
  • useLocation: retorna o objeto de localização atual.
  • useNavigate: retorna a função para navegar programaticamente.
  • useParams: retorna os parâmetros de URL e as correspondências dos URLs do caminho de rota.
  • useResolvedPath: retorna o caminho do URL resolvido.

O roteamento pré-carregará todas as rotas aninhadas e as entregará em paralelo. Isso pode resultar em uma carga inicial um pouco mais longa, mas o tempo interativo será menor.

Vamos ver a guia de rede na legenda abaixo. Podemos ver como o Remix carrega todas as rotas aninhadas em paralelo:

Como os ativos são carregados

Um recurso interessante sobre o roteamento é que ele contará com navegação HTML. Isso significa que não precisaremos de JavaScript para fazê-lo funcionar corretamente o sistema de roteamento funcionará melhor quando o JavaScript estiver presente. Deve gostar do recurso Forms, ele só melhorará seu comportamento quando o JavaScript estiver disponível. O roteamento Remix oferece suporte à configuração meta no escopo da rota, tudo o que precisamos fazer é exportar uma metafunção na página do módulo.

import type { MetaFunction } from "remix";

export const meta: MetaFunction = () => {
  return {
    title: "Create New Post",
    description:
      "Application for creating posts."
  };
};
Enter fullscreen mode Exit fullscreen mode

6º) Desenvolvimento Rápido

O framework Remix não usa mais o Webpack, em vez disso ele se baseia em esbuild e isso o torna super rápido.

esbuild

Atualmente, ele suporta os seguintes recursos:

  • Módulos ES6 e CommonJS
  • Agitação da árvore dos módulos ES6
  • Sintaxe TypeScript e JSX
  • Mapas de origem
  • Minificação
  • Plug-ins

Este construtor é construído com a linguagem de programação Go e é mantido principalmente por um Ewan Wallace. Infelizmente, não atingiu o 1.0.0 portanto, podemos esperar alguns bugs e problemas aqui e ali. No entanto, agora está longe do estágio alfa podemos pensar nisso como um estágio Beta. Eu pessoalmente acho que o construtor escolhido pelo Next.js é mais estável e maduro. Só o tempo dirá se este vale a pena.

Mencionei apenas algumas de suas principais características que venho observando, mas tem muito mais do que isso. Por exemplo, a documentação é excelente, intuitiva e divertida.

Fontes onde pesquisei esse conteúdo:

Top comments (2)

Collapse
 
erlan profile image
erlan

Obrigado pelo artigo em pt-br, estou testando o remix em um projeto pessoal e estou adorando ;)

Collapse
 
vedovelli profile image
Fábio Vedovelli • Edited

Hey, excelente artigo!

Reparei em partes que precisam ser atualizadas. A convenção atual é tipar os argumentos de uma loader function e não seu retorno.

async function loader({request, params}: LoaderArgs) {} 
Enter fullscreen mode Exit fullscreen mode

Outro ponto é o retorno da loader function, que no exemplo está num formato que eu nunca vi. Normalmente se usa o utilitário json() para retornar dados de uma loader function.

// ✅ retornando os resultados
  return json( // mais acima no código import {json} from '@remix-run/react'
    res.json()
  );
Enter fullscreen mode Exit fullscreen mode