Personalizar as dependências de autenticação

O design modular do SDK do Firebase para JavaScript oferece muito mais controle para você criar apps. Essa flexibilidade permite personalizar as dependências da plataforma e otimizar o tamanho do pacote removendo os recursos que não são necessários.

Há duas maneiras de inicializar a biblioteca do Auth: as funções getAuth() e initializeAuth(). A primeira, getAuth(), fornece tudo que o app precisa para aproveitar todos os recursos que a biblioteca do Auth oferece. O lado negativo é que ela extrai uma grande quantidade de código que provavelmente não será usado pelo app. Ela também pode extrair código que simplesmente não é suportado na plataforma de destino, levando a erros. Para evitar esses problemas, use initializeAuth(), que usa um mapa de dependências. A função getAuth() simplesmente chama initializeAuth() com todas as dependências especificadas. Para ilustrar, aqui está o equivalente a getAuth() em ambientes de navegador:

import {initializeAuth, browserLocalPersistence, browserPopupRedirectResolver, browserSessionPersistence, indexedDBLocalPersistence} from "firebase/auth";
import {initializeApp} from "firebase/app";

const app = initializeApp({/** Your app config */});
const auth = initializeAuth(app, {
  persistence: [indexedDBLocalPersistence, browserLocalPersistence, browserSessionPersistence],
  popupRedirectResolver: browserPopupRedirectResolver,
});

Como personalizar dependências

Nem todos os apps usam a família de funções signInWithPopup ou signInWithRedirect. Muitos apps não precisarão da flexibilidade que indexedDB fornece ou não precisarão ser suportados por indexedDB e localStorage ao mesmo tempo, caso uma delas não esteja disponível. Nesses casos, a getAuth() padrão inclui muito código não usado que aumenta os tamanhos dos pacotes sem motivo. Em vez disso, esses apps podem personalizar as dependências. Por exemplo, se um app usa apenas autenticação por link de e-mail e localStorage for suficiente (porque você não está usando scripts da Web ou de service worker), é possível remover uma grande quantidade de inchaço de código inicializando o Auth desta maneira:

import {initializeAuth, browserLocalPersistence} from "firebase/auth";
import {initializeApp} from "firebase/app";

const app = initializeApp({/** Your app config */});
const auth = initializeAuth(app, {
  persistence: browserLocalPersistence,
  // No popupRedirectResolver defined
});

Com esse código, você removeu três grandes dependências que o app não precisa, reduzindo significativamente a quantidade de largura de banda que os usuários usam sempre que acessam seu site.

Considerações específicas da plataforma

Em muitos casos, você precisa definir manualmente as dependências do Auth para evitar erros na inicialização. A função getAuth() pressupõe uma plataforma específica. Para o ponto de entrada padrão, ela é um ambiente de navegador, e para o ponto de entrada do Cordova, um ambiente do Cordova. No entanto, às vezes as necessidades de um aplicativo específico entram em conflito com essas suposições. Para scripts da Web e de service worker, por exemplo, a implementação padrão getAuth() extrai o código que lê do objeto window, o que causará erros. Nesses casos, é necessário personalizar as dependências. O código a seguir é apropriado para inicializar a biblioteca do Auth em um contexto de service worker:

import {initializeAuth, indexedDBLocalPersistence} from "firebase/auth";
import {initializeApp} from "firebase/app";

const app = initializeApp({/** Your app config */});
const auth = initializeAuth(app, {
  persistence: indexedDBLocalPersistence,
  // No popupRedirectResolver defined
});

Esse código instrui o Auth a inicializar com a persistência indexedDB (que está disponível nos contextos do worker) e omite a dependência popupRedirectResolver, que presume que um contexto DOM está disponível.

Há outros motivos para você definir dependências manualmente em determinadas plataformas. Ao definir o campo popupRedirectResolver na inicialização do Auth, em alguns casos a biblioteca realizará trabalho adicional na inicialização. Em navegadores para dispositivos móveis, a biblioteca abre automaticamente um iframe para o domínio Auth de maneira preemptiva. Isso é feito para tornar a experiência perfeita para a maioria dos usuários, mas pode afetar o desempenho carregando código adicional durante a inicialização do app. Esse comportamento pode ser evitado com o uso de initializeAuth() e transmitindo manualmente a dependência browserPopupRedirectResolver para as funções que precisam dela:

import {initializeAuth, browserLocalPersistence, browserPopupRedirectResolver, indexedDBLocalPersistence, signInWithRedirect, GoogleAuthProvider} from "firebase/auth";
import {initializeApp} from "firebase/app";

const app = initializeApp({/** Your app config */});
const auth = initializeAuth(app, {
  persistence: [indexedDBLocalPersistence, browserLocalPersistence],
});

// Later
signInWithRedirect(auth, new GoogleAuthProvider(), browserPopupRedirectResolver);

Se tivéssemos fornecido browserPopupRedirectResolver nas dependências para initializeAuth(), o terceiro parâmetro na chamada para signInWithRedirect() não seria necessário. No entanto, ao mover essa dependência para a chamada para signInWithRedirect() diretamente, o hit de desempenho inicial durante a inicialização é removido. Há vantagens e desvantagens com a movimentação da dependência, mas a parte importante é que você pode tomar decisões sobre essas vantagens inicializando manualmente a biblioteca.

Quando usar a inicialização personalizada

Em resumo, a inicialização personalizada oferece um controle muito maior sobre o uso do SDK do Auth pelo app. A função getAuth() padrão é boa para dar os primeiros passos e atende à maioria dos casos de uso. Para a maioria dos apps, getAuth() pode ser tudo o que você precisa. No entanto, há muitos motivos para querer ou precisar mudar para o gerenciamento manual de dependências:

  • Para apps em que o tamanho do pacote e os tempos de carregamento são extremamente importantes, a inicialização personalizada do Auth pode reduzir muitos kilobytes de dados. Ela também pode reduzir os tempos de carregamento inicial movendo as dependências para tempo de uso em vez de tempo de inicialização.
  • Para código executado em contextos não DOM (como Web e service workers), é necessário usar initializeAuth() para evitar erros.