Introdução
Supabase é uma alternativa de código aberto ao Firebase. Este é um título em negrito, porque o Firebase se destina a ser uma solução completa, com vários recursos como autenticação, armazenamento de arquivos, funções sem servidor, SDK e muito mais.
Embora o Firebase tenha muitos recursos, o Supabase pode ser mais útil porque usa tecnologia de código aberto. O Supabase oferece a flexibilidade de hospedar em sua máquina local, em um provedor de serviços em nuvem ou mesmo como um contêiner Docker. Isso significa que é livre de restrições, portanto, não há bloqueio de fornecedor.
Supabase usa PostgreSQL sob o capô para o banco de dados e escuta o real-o tempo muda por meio de várias ferramentas que eles constroem.
Atualmente, o Supabase oferece suporte apenas a recursos como bancos de dados, autenticação e armazenamento. Eles também têm funções sem servidor, embora ainda estejam em estágio de desenvolvimento.
Supabase se destaca pelos seguintes motivos:
- Supabase lida com o dimensionamento para você (embora use um banco de dados SQL)
- Ao contrário do Firebase, você pode realizar consultas complexas ou pesquisas de texto
- A migração de dados é direta no Supabase, pois usa PostgreSQL, então você pode importar dados por meio de um arquivo.sql
Existem, no entanto, várias desvantagens em usar o Supabase. Eles incluem:
- Recursos limitados
- Requer que você habilite os recursos de replicação para uma tabela para receber atualizações em tempo real
- Quando as atualizações em tempo real estão ativadas, as políticas de segurança do Supabase não se aplicam
- Seu SDK suporta apenas JavaScript (o suporte para outros idiomas ainda está em beta)
Armazenamento com Supabase
O Supabase fornece armazenamento de objeto de código aberto que pode conter qualquer tipo de arquivo com alta escalabilidade incorporada. Ele fornece uma API conveniente que permite políticas e permissões personalizadas.
Alguns recursos como integração de CDN e auto transformação e otimização (redimensionamento e compactação de mídia) estarão disponíveis em breve. Com a adição desses recursos, o armazenamento Supabase será um forte concorrente do armazenamento Firebase.
Autenticação com Supabase
Cada projeto Supabase vem com autenticação integrada, autorização e gerenciamento de usuário sem a necessidade de nenhuma outra ferramenta.
O Supabase fornece uma API simples para integrar provedores de serviços de autenticação de terceiros, como Google, Apple, Twitter, Facebook, Github, Azure, Gitlab e Bitbucket. Ele também oferece suporte a logins corporativos, como SAML.
Como Supabase gerencia dados em tempo real
Supabase usa várias ferramentas com PostgreSQL para fornecer atualizações em tempo real. Eles são os seguintes:
- Tempo real permite que você ouça eventos no PostgreSQL como inserções, atualizações e exclui e converte dados em formato JSON usando WebSockets
- Postgres-meta permite que você consulte PostgreSQL por meio de uma API REST
- PostgREST transforma o banco de dados PostgreSQL em uma API RESTful
- GoTrue gerencia usuários por meio de uma API SWT que gera tokens SWT
- Kong é um gateway de API nativo da nuvem
Por meio do diagrama de arquitetura acima, você pode ver como o Supabase habilita dados em tempo real com PostgreSQL.
Primeiros passos com Supabase
Nesta seção, vamos ver como podemos criar um banco de dados no Supabase e permitir atualizações em tempo real para ele.
Primeiro, vamos entrar e criar uma organização a partir do painel Supabase. Em seguida, na guia projeto , clique no botão criar projeto . Isso solicitará que você insira o nome do banco de dados, a senha e a região onde deseja hospedar seu banco de dados:
Em seguida, precisamos criar uma tabela a partir do painel do projeto na guia tabela . Esta seção solicitará que você insira o nome do banco de dados e os campos do banco de dados (chave primária e outros) junto com o tipo de dados.
Criaremos uma chave primária com tipo de dados UUID com geração automática habilitada:
Agora precisamos habilitar esta tabela para receber atualizações em tempo real. Vá para a guia banco de dados na barra lateral esquerda.
A seguir, selecione a guia replicação . Esta seção exibirá uma tabela de tabelas que você criou. Habilite o recurso de replicação para uma tabela específica, assim:
Agora que criamos um banco de dados e uma tabela com replicação habilitada, vamos ver como usar os métodos de API do SDK do Supabase JavaScript.
API Supabase JavaScript
A API Supabase JavaScript fornece métodos fáceis de entender. Como estamos lidando com SQL, os métodos da API são semelhantes às consultas SQL:
const {dados, erro}=espera supabase .from ('pokemon') .inserir([ {nome:'Pikachu', poder:'Fogo', descrição:'Fofo'}, ])
O código acima é para inserir uma linha em uma tabela chamada pokemon
. Observe como o objeto de conexão Supabase seleciona a tabela e a operação como uma consulta SQL.
A consulta de dados no Supabase é semelhante a uma instrução select no SQL:
deixe {dados: pokemon, erro}=esperar supabase .from ('pokemon') .select ("*")
Mais opções de filtro estão disponíveis com o objeto de consulta Supabase. Eles serão semelhantes à cláusula where
e like
em uma consulta SQL:
.eq (), .gt (), .lt (), .Como() , .é() , .dentro()
Usando Supabase com React
Vamos ver como podemos integrar Supabase com React com Criar aplicativo React . Para este exemplo, vamos criar um pequeno aplicativo Pokémon que mantém dados sobre o seu Pokémon favorito.
Primeiro, vamos criar um aplicativo React:
npx create-react-app supabase-pokemons
Agora vamos instalar as dependências de que precisaremos para construir este aplicativo Pokémon. Estaremos usando IU semântica para construir a IU:
yarn add @ supabase/supabase-js semantic-ui-react semantic-ui-css react-router-dom
Agora vamos estruturar os diretórios do projeto. Como este é um aplicativo pequeno, usaremos a API de contexto do React.
Primeiro, vamos criar um arquivo.env na raiz do projeto com as seguintes chaves:
REACT_APP_SUPABASE_URL=REACT_APP_SUPABASE_KEY=
Essas chaves estão disponíveis no painel do Supabase na seção configurações :
Agora, vamos criar a conexão Supabase em util/connection.js com o seguinte snippet de código:
import {createClient} de'@ supabase/supabase-js'; const REACT_APP_SUPABASE_URL=process.env.REACT_APP_SUPABASE_URL; const REACT_APP_SUPABASE_KEY=process.env.REACT_APP_SUPABASE_KEY; export const supabase=createClient (REACT_APP_SUPABASE_URL, REACT_APP_SUPABASE_KEY); arquivo connection.js
Vamos adicionar a funcionalidade de login ao aplicativo com provedores de serviços terceirizados integrados, como Google e Github:
const signIn=async ()=> { esperar supabase.auth.signIn ({email: credentials.email, senha: credentials.password}); Claro(); } const signUp=async ()=> { esperar supabase.auth.signUp ({email: credentials.email, senha: credentials.password}) Claro(); }
Como você pode ver, o gerenciamento de usuários é simples de manter. Você pode criá-lo com algumas linhas de código.
Integração com Google e Github
A seguir, vamos ver como podemos integrar com o Google e o Github. Primeiro, você precisará criar chaves secretas do provedor de autenticação específico e adicioná-las ao Supabase por meio do painel:
const gitHub=async ()=> {
await supabase.auth.signIn ({ provedor:'github' }) }
Você pode usar o código acima para integrar qualquer outro provedor de autenticação de terceiros compatível com o Supabase.
É apenas uma questão de alterar o nome do provedor, e a Supabase cuidará do resto para você:
import {useState, useEffect, useContext} de"react" importar AppContext de"../AppContext"; import {useHistory} de"react-router-dom"; import {Grid, GridColumn, GridRow, Form, FormField, Input, Icon, Button, Header, Segment} from"semantic-ui-react" const initState={email:'', senha:'', passwordConfirm:''} function Login ({supabase}) { let history=useHistory (); const [isSignIn, setSignIn]=useState (false); const [credenciais, setCredentials]=useState (initState); const {usuário, isLoggedIn, login, logout}=useContext (AppContext) useEffect (()=> { const {data: authListener}=supabase.auth.onAuthStateChange ( assíncrono (evento, sessão)=> { const currentUser=sessão?.user; login (sessão.usuário) } ); return ()=> { authListener?.unsubscribe (); }; }, [do utilizador]); useEffect (()=> { if (isLoggedIn) { history.push ("/home"); } }, [isLoggedIn]) const onChange=(tipo, valor)=> { setCredentials ({... credentials, [type]: value}) } const clear=()=> { setCredentials (initState) } const signIn=async ()=> { esperar supabase.auth.signIn ({email: credentials.email, senha: credentials.password}); Claro(); } const signUp=async ()=> { esperar supabase.auth.signUp ({email: credentials.email, senha: credentials.password}) Claro(); } const gitHub=async ()=> { aguarde supabase.auth.signIn ({ provedor:'github' }) } const google=async ()=> { aguarde supabase.auth.signIn ({ provedor:'google' }) } Retorna (<Ícone do botão labelPosition=fluido'esquerdo'onClick={gitHub}> Github <Ícone do botão labelPosition=fluido'esquerdo'onClick={google}> ) } exportar login padrão Arquivo Login.js
Criação de um arquivo AppContext.js
A seguir, vamos criar o contexto para o aplicativo que manterá nossos dados de aplicativo.
Adicione um arquivo AppContext.js
e um redutor para o contexto do aplicativo chamado AppReducer.js
no diretório src:
import {createContext, useReducer} de"react"; importar AppReducer de"./AppReducer" const initialState={ usuário: nulo, Pokémon: null, pokemons: [], isEditing: false, isLoggedIn: false, } const AppContex=createContext (initialState) export const AppContextProvider=({children})=> { const [estado, despacho]=useReducer (AppReducer, initialState); const login=(dados)=> {envio ({tipo:'LOGIN', carga útil: dados})} const logout=(data)=> {dispatch ({type:'LOGOUT', payload: data})} const getPokemons=(data)=> {dispatch ({type:'GET_POKEMONS', payload: data})} const selectPokemon=(data)=> {dispatch ({type:'SELECT_POKEMON', payload: data})} const createPokemon=(data)=> {dispatch ({type:'CREATE_POKEMON', payload: data})} const updatePokemon=(data)=> {dispatch ({type:'UPDATE_POKEMON', payload: data})} const deletePokemon=(data)=> {dispatch ({type:'DELETE_POKEMON', payload: data})} Retorna ({crianças} ) } exportar AppContex padrão; Arquivo AppContex.js const deleteItem=(pokemons, {id})=> { return pokemons.filter ((pokemon)=> pokemon.id!==id) } const updateItem=(pokemons, dados)=> { deixe pokemon=pokemons.find ((pokemon)=> pokemon.id===data.id); deixe updatedPokemon={... pokemon,... data}; deixe pokemonIndex=pokemons.findIndex ((pokemon)=> pokemon.id===data.id); Retorna [ ... pokemons.slice (0, pokemonIndex), updatedPokemon, ... pokemons.slice (++ pokemonIndex), ]; } const AppReducer=(estado, ação)=> { switch (action.type) { case'GET_POKEMONS': Retorna { ...Estado, pokemons: action.payload }; case'SELECT_POKEMON': Retorna { ...Estado, isEditing: true, pokemon: action.payload } case'CREATE_POKEMON': Retorna { ...Estado, pokemons: [action.payload,... state.pokemons] }; case'UPDATE_POKEMON': Retorna { ...Estado, isEditing: false, pokemons: updateItem (state.pokemons, action.payload) }; case'DELETE_POKEMON': Retorna { ...Estado, pokemons: deleteItem (state.pokemons, action.payload) }; case'LOGIN': Retorna { ...Estado, usuário: action.payload, isLoggedIn: true }; case'LOGOUT': Retorna { ...Estado, usuário: nulo, isLoggedIn: false }; padrão: estado de retorno } } exportar AppReducer padrão Arquivo AppReducer.js
Adicionando dados ao aplicativo
Agora avançamos para o nosso primeiro uso do Supabase. Aqui, começaremos adicionando dados à tabela Pokémon de um componente chamado PokemonForm.jsx
.
Nesse arquivo, vamos criar duas funções para criar e atualizar o Pokémon:
const createPokemon=async ({name, power, description})=> { tentar { aguardar supabase .from ('pokemon') .inserir([ {nome, poder, descrição} ]); } catch (erro) { } finalmente { Claro(); } }
A função acima é responsável por criar um Pokémon. Como temos uma tabela com um campo de ID do tipo UUID, ela criará um ID exclusivo para cada linha de dados.
Agora observe que cada comando de Supabase retorna uma promessa para que você possa usar Async
/ Await
para lidar com ações assíncronas. As funções de atualização serão as seguintes:
const updatePokemon=async ({id, name, power, description})=> {
tente { aguardar supabase .from ('pokemon') .atualizar([ {nome, poder, descrição} ]). match ({id: id}) } catch (erro) { } finalmente { Claro(); } }
Você pode consultar todo o código do snippet abaixo:
import {useEffect, useState, useContext} de"react" importar AppContex de"../AppContext" import {Form, FormField, Header, Input, Button, Segment} from'semantic-ui-react' const initState={nome:'', potência:'', descrição:''} function PokemonForm ({supabase}) { const {isEditing, pokemon}=useContext (AppContex) const [newPokemon, setNewPokemon]=useState (initState); useEffect (()=> { if (Pokémon) { setNewPokemon (Pokémon) } }, [Pokémon]) const createPokemon=async ({nome, poder, descrição})=> { tentar { aguardar supabase .from ('pokemon') .inserir([ {nome, poder, descrição} ]); } catch (erro) { } finalmente { Claro(); } } const updatePokemon=async ({id, nome, poder, descrição})=> { tentar { aguardar supabase .from ('pokemon') .atualizar([ {nome, poder, descrição} ]). match ({id: id}) } catch (erro) { } finalmente { Claro(); } } const onChange=(tipo, valor)=> { setNewPokemon ({... pokemon, [type]: value}) } const clear=()=> { setNewPokemon (initState) } const cancel=()=> { Claro() } Retorna () } exportar PokemonForm padrão
Da mesma forma, você pode excluir um Pokémon específico executando o código abaixo:
const deletePokemon=async (id)=> { aguardar supabase .from ('pokemon') .delete (). match ({id: id}) }
Observe que passamos o ID (que é o UUID gerado automaticamente pelo Supabase) que pesquisará o Pokémon pelo ID fornecido e executará a exclusão.
Criação de um ouvinte de evento
A seguir, vamos criar um assinante de evento que ouvirá eventos em tempo real em todo o aplicativo. Como estamos nos inscrevendo no evento, o lugar ideal para ouvi-los seria o gancho de ciclo de vida useEffect
no React.
Vamos criar o ouvinte de evento no arquivo Home.jsx
:
useEffect (()=> { supabase .from ('pokemon') .select (). then (({data})=> {getPokemons (data)}) assinatura const=supabase .from ('pokemon') .on ('*', carga útil=> { alterPokemons (carga útil) }) .se inscrever() return ()=> supabase.removeSubscription (assinatura) }, []);
Observe como criamos os ouvintes de evento e a função de limpeza para o estágio de desmontagem do aplicativo com o retorno do useEffect
.
O objeto Supabase fornece uma função API chamada .on ()
que aceita dois parâmetros. O primeiro argumento é o tipo de evento e o segundo parâmetro é a função de retorno de chamada.
Existem vários eventos que o Supabase escuta. São eles:
-
INSERT
: escuta eventos de inserção de dados -
UPDATE
: escuta eventos de atualização de dados -
DELETE
: escuta eventos de exclusão de dados -
*
: escuta todos os eventos que ocorrem por meio do aplicativo
Agora, para ouvir todos os eventos que ocorrem no aplicativo, vamos criar uma função que irá disparar uma função redutora com base no tipo de evento:
const alterPokemons=(carga útil)=> { switch (payload.eventType) { case"INSERT": createPokemon (payload.new); pausa; case"DELETE": deletePokemon (payload.old); pausa; case"UPDATE": return updatePokemon (payload.new) padrão: createPokemon (payload.new); } }
Esta função irá disparar dentro da função .on ()
. Observe que a carga útil retorna três valores importantes.
Eles são:
-
eventType
: tipos de eventosINSERT
,UPDATE
eDELETE
-
novo
: novos dados/dados atualizados -
old
: dados antigos
Por meio dos snippets de código acima, você pode ver por que o Supabase está se tornando uma alternativa competitiva ao Firebase. A API de Supabase fornece todos os recursos interessantes com apenas algumas linhas de código em comparação com outros serviços.
Você pode percorrer o código deste projeto com o seguinte repositório GitHub .
Conclusão
Em conclusão, Supabase é o melhor código aberto alternativa ao Firebase do Google. Ele oferece alguns recursos interessantes com o poder do PostgreSQL e não tem nenhuma limitação com tipos de dados como outras soluções de banco de dados em tempo real.
Você pode encontrar mais informações sobre o Supabase consultando sua documentação .
Obrigado por reservar um tempo para ler isto. Gostaria de ver suas perguntas e comentários sobre o tema na seção de comentários abaixo. Saúde!
A postagem Intro to Supabase apareceu primeiro em LogRocket Blog .