Skip to content

Slash vs React

Esta página compara Slash e React em termos de arquitetura, performance, DX (Developer Experience) e casos de uso. Ambas são excelentes bibliotecas, mas com filosofias e trade-offs diferentes.

AspectoSlashReact
Virtual DOM❌ Não✅ Sim
ReatividadeObserver Pattern (re-render por componente que lê o state)Re-render component tree
SSR✅ renderToString/renderToStream no pacote✅ react-dom/server (frameworks adicionam roteamento e data loading)
Ecossistema🌱 Crescendo🌳 Maduro e extenso
Curva de AprendizadoBaixaMédia
ToolingTypeScript nativoExcelente (DevTools, etc)

React usa um Virtual DOM para comparar estados e fazer updates eficientes:

// React
import { useState } from 'react'
function Counter() {
const [count, setCount] = useState(0)
// Todo o componente re-renderiza quando count muda
console.log('Component rendered')
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
)
}

Como funciona:

  1. State muda via setCount()
  2. React agenda re-render do componente
  3. Componente executa novamente (função é chamada)
  4. React compara Virtual DOM antigo vs novo
  5. Aplica apenas as diferenças no DOM real

Slash usa um sistema de estado reativo baseado em Observer Pattern: um componente que lê state.get() re-executa quando o state muda e seus nós são substituídos, sem diff de Virtual DOM:

// Slash
import { html, createState } from '@_bashell/slash'
// O state fica fora do componente: se fosse criado dentro, seria recriado a cada render
const count = createState(0)
// Monte como <${Counter} />
function Counter() {
// Componente re-executa quando count muda (porque leu count.get())
console.log('Component rendered')
return html`
<div>
<p>Count: ${count.get()}</p>
<button onClick=${() => count.set(count.get() + 1)}>
Increment
</button>
</div>
`
}

Como funciona:

  1. State muda via count.set()
  2. O componente que leu count.get() executa de novo
  3. Os nós anteriores do componente são substituídos pelos novos
  4. Sem diff de Virtual DOM
  5. A granularidade é o componente: divida a interface em componentes pequenos para re-renderizar só o necessário

Esta página não traz benchmarks nem comparação de tamanho com o React: não há medições reproduzíveis no repositório para sustentá-las. Meça no seu caso de uso.

Para o Slash, o repositório mede o tamanho de um app mínimo (createState + html + render, minificado) com bun test scripts/bundle-size.test.ts no pacote core. Resultado medido: ≈ 8,3 KB gzip. O número depende do que seu app importa.


// React
import { useState } from 'react'
function Greeting({ name }) {
const [count, setCount] = useState(0)
return (
<div>
<h1>Hello {name}</h1>
<p>Clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click
</button>
</div>
)
}
// Slash
import { html, createState } from '@_bashell/slash'
// Slash não tem estado local por instância: o state vive fora do componente
// (dentro dele seria recriado a cada render). Monte como <${Greeting} name="..." />
const count = createState(0)
function Greeting({ name }) {
return html`
<div>
<h1>Hello ${name}</h1>
<p>Clicked ${count.get()} times</p>
<button onClick=${() => count.set(count.get() + 1)}>
Click
</button>
</div>
`
}

Observações:

  • React tem mais boilerplate (useState, useEffect, etc)
  • Slash é mais direto, mas não tem estado local nem hooks de efeito: o state fica fora do componente e efeitos/cleanup são por sua conta
  • Ambos têm boa DX, mas Slash é mais minimalista

Vantagens:

  • ✅ Ecossistema gigantesco
  • ✅ Frameworks (Next.js, Remix, Gatsby)
  • ✅ UI libraries (MUI, Chakra, Ant Design)
  • ✅ DevTools excelentes
  • ✅ Comunidade massiva
  • ✅ Recursos de aprendizado abundantes

Exemplos:

Terminal window
# Frameworks
npx create-next-app
npx create-remix
# UI Libraries
npm install @mui/material
npm install chakra-ui
# State Management
npm install zustand
npm install jotai
npm install redux

Vantagens:

  • ✅ Sem dependências externas
  • ✅ TypeScript first-class
  • ✅ SSR nativo
  • ✅ Router integrado
  • ✅ Data loading isomórfico

Status Atual:

  • 🌱 Ecossistema em crescimento
  • 📦 Foco em simplicidade e zero config
  • 🎯 Ideal para apps pequenos/médios

  1. Aplicações Empresariais Grandes

    • Múltiplos times
    • Necessidade de UI libraries maduras
    • Ecosistema extenso importante
  2. Necessidade de Frameworks Específicos

    • Next.js para SSR/SSG avançado
    • Remix para data loading
    • Gatsby para sites estáticos
  3. Contratação e Onboarding

    • Pool de desenvolvedores React é enorme
    • Curva de aprendizado conhecida
    • Material de treinamento abundante
  4. Mobile (React Native)

    • Código compartilhado web/mobile
    • Ecosistema maduro
  1. Controle sobre o DOM

    • Atualizações diretas, sem Virtual DOM
    • Integração com código DOM existente
    • Aplicações com poucas dependências
  2. Bundle Size Limitado

    • Um app mínimo mede ≈ 8,3 KB gzip (veja a seção Performance)
    • Quando cada dependência conta
    • Embedded apps
  3. Simplicidade e Rapidez de Desenvolvimento

    • Protótipos rápidos
    • MVPs
    • Apps pequenas/médias
  4. SSR Simples Sem Frameworks

    • Blog estático com interatividade
    • Landing pages dinâmicas
    • Sites de documentação
  5. Aprendizado de Fundamentos

    • Entender reatividade
    • Aprender DOM manipulation
    • Projetos educacionais

O que é similar:

  • Componentes funcionais
  • Props e children
  • Event handlers
  • Conditional rendering

O que muda:

  • useState → createState
  • useEffect → state.watch() (criado fora do componente; não há onCleanup público)
  • useMemo → Não necessário (pode usar funções puras)
  • JSX → html template tag (ou hyperscript)

Exemplo de migração:

// React
function TodoItem({ todo, onToggle }) {
const [isEditing, setIsEditing] = useState(false)
return (
<li>
{isEditing ? (
<input defaultValue={todo.text} />
) : (
<span onClick={() => onToggle(todo.id)}>
{todo.text}
</span>
)}
<button onClick={() => setIsEditing(!isEditing)}>
Edit
</button>
</li>
)
}
// Slash
import { html, createState } from '@_bashell/slash'
// Sem estado local por instância: guarde qual item está em edição fora do componente
const editingId = createState<number | null>(null)
function TodoItem({ todo, onToggle }) {
const isEditing = editingId.get() === todo.id
return html`
<li>
${isEditing ? html`
<input value=${todo.text} />
` : html`
<span onClick=${() => onToggle(todo.id)}>
${todo.text}
</span>
`}
<button onClick=${() => editingId.set(isEditing ? null : todo.id)}>
Edit
</button>
</li>
`
}

Prós:

  • ✅ Ecossistema maduro e extenso
  • ✅ Ferramentas de desenvolvimento excelentes
  • ✅ Grande comunidade e recursos
  • ✅ Padrões estabelecidos
  • ✅ React Native para mobile

Contras:

  • ❌ Mais dependências (react e react-dom)
  • ❌ Mais boilerplate (hooks, etc)
  • ❌ Re-renders podem ser confusos
  • ❌ SSR com roteamento e data loading costuma exigir um framework

Prós:

  • ✅ Bundle pequeno (app mínimo medido em ≈ 8,3 KB gzip, veja a seção Performance)
  • ✅ API minimalista e direta
  • ✅ SSR nativo
  • ✅ TypeScript first-class
  • ✅ Sem dependências

Contras:

  • ❌ Ecossistema menor
  • ❌ Comunidade pequena
  • ❌ Menos recursos de aprendizado
  • ❌ Sem mobile (por enquanto)
  • ❌ Ferramentas de dev em desenvolvimento

Escolha React se:

  • Precisa de ecossistema maduro
  • Trabalha em time grande
  • Necessita de UI libraries prontas
  • Quer React Native
  • Valoriza estabilidade e padrões

Escolha Slash se:

  • Quer uma biblioteca pequena e sem dependências
  • Bundle size é limitação (app mínimo: ≈ 8,3 KB gzip)
  • Prefere simplicidade
  • Gosta de controle direto
  • App pequena/média
  • Quer aprender conceitos fundamentais

Ambas são excelentes. A escolha depende do contexto do projeto e preferências da equipe.