Neste codelab, melhore o desempenho do aplicativo a seguir removendo todas as dependências não usadas e desnecessárias.
Medida
É sempre bom avaliar o desempenho de um site antes de adicionar otimizações.
- Para visualizar o site, pressione Ver app. Em seguida, pressione Tela cheia .
Vá em frente e clique no seu gatinho favorito! O Realtime Database do Firebase é usado neste aplicativo. É por isso que a pontuação é atualizada em tempo real e é sincronizada com todas as outras pessoas que usam o aplicativo. 🐈
- Pressione "Control + Shift + J" (ou "Command + Option + J" no Mac) para abrir o DevTools.
- Clique na guia Rede.
- Marque a caixa de seleção Desativar cache.
- Atualize o app.
Quase 1 MB de JavaScript está sendo enviado para carregar este aplicativo simples.
Confira os avisos do projeto no DevTools.
- Clique na guia Console.
- Verifique se
Warnings
está ativado no menu suspenso de níveis ao lado da entradaFilter
.
- Confira o aviso exibido.
O Firebase, que é uma das bibliotecas usadas neste aplicativo, está sendo um bom samaritan ao fornecer um aviso para que os desenvolvedores saibam que não devem importar todo o pacote, mas apenas os componentes usados. Em outras palavras, há bibliotecas não utilizadas que podem ser removidas nesse aplicativo para que ele seja carregado mais rápido.
Também há casos em que uma biblioteca específica é usada, mas pode haver uma alternativa mais simples. O conceito de remoção de bibliotecas desnecessárias é explorado posteriormente neste tutorial.
Como analisar o pacote
Há duas dependências principais no aplicativo:
- Firebase: plataforma que oferece vários serviços úteis para apps iOS, Android ou da Web. Aqui, o Realtime Database é usado para armazenar e sincronizar as informações de cada gatinho em tempo real.
- Moment.js: uma biblioteca de utilitários que facilita o processamento de datas no JavaScript. A data de nascimento de cada gatinho é armazenada no banco de dados do Firebase, e
moment
é usado para calcular a idade em semanas.
Como apenas duas dependências contribuem para um tamanho de pacote de quase 1 MB? Bem, um dos motivos é que qualquer dependência pode, por sua vez, ter as próprias dependências, de modo que há muito mais do que apenas duas se cada profundidade/ramificação da "árvore" de dependência for considerada. É fácil um aplicativo se tornar grande relativamente rápido se muitas dependências forem incluídas.
Analise o bundler para ter uma ideia melhor do que está acontecendo. Há várias
ferramentas criadas pela comunidade que podem ajudar com isso, como o
webpack-bundle-analyzer
.
O pacote dessa ferramenta já está incluído no app como um devDependency
.
"devDependencies": {
//...
"webpack-bundle-analyzer": "^2.13.1"
},
Ou seja, ele pode ser usado diretamente no arquivo de configuração do webpack.
Importe-o no início de webpack.config.js
:
const path = require("path");
//...
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
.BundleAnalyzerPlugin;
Agora adicione-o como um plug-in no final do arquivo, na matriz plugins
:
module.exports = {
//...
plugins: [
//...
new BundleAnalyzerPlugin()
]
};
Quando o aplicativo for recarregado, você terá uma visualização de todo o pacote, em vez do app em si.
Não é tão fofo quanto ver alguns gatinhos Deliver, mas incrivelmente útil mesmo assim. Passar o cursor sobre qualquer um dos pacotes mostra o tamanho dele representado de três maneiras diferentes:
Tamanho da estatística | Tamanho antes de qualquer minificação ou compactação. |
---|---|
Tamanho analisado | Tamanho do pacote real dentro do pacote após a compilação. A versão 4 do webpack (que é usada neste aplicativo) minimiza os arquivos compilados automaticamente, e é por isso que ele é menor que o tamanho da estatística. |
Tamanho Gzip | Tamanho do pacote após a compactação com a codificação gzip. Esse tópico é abordado em um guia separado. |
Com a ferramenta webpack-bundle-analyzer, é mais fácil identificar pacotes não utilizados ou desnecessários que compõem uma grande porcentagem do pacote.
Como remover pacotes não utilizados
A visualização mostra que o pacote firebase
consiste muito mais do que apenas um banco de dados. Ele inclui outros pacotes, como:
firestore
auth
storage
messaging
functions
Todos esses serviços são incríveis fornecidos pelo Firebase. Consulte a documentação para saber mais, mas nenhum deles está sendo usado no aplicativo. Por isso, não há motivo para importar todos.
Reverta as mudanças em webpack.config.js
para conferir o aplicativo de novo:
- Remova
BundleAnalyzerPlugin
da lista de plug-ins:
plugins: [
//...
new BundleAnalyzerPlugin()
];
- Agora remova a importação não utilizada da parte superior do arquivo:
const path = require("path");
//...
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
Agora, o aplicativo deve ser carregado normalmente. Modifique src/index.js
para atualizar as importações do Firebase.
import firebase from 'firebase';
import firebase from 'firebase/app';
import 'firebase/database';
Agora, quando o app for recarregado, o aviso do DevTools não será exibido. Abrir o painel Rede do DevTools também mostra uma boa redução no tamanho do pacote:
Mais da metade do tamanho do pacote foi removido. O Firebase oferece muitos serviços diferentes e dá aos desenvolvedores a opção de incluir apenas os que são realmente
necessários. Neste aplicativo, apenas firebase/database
foi usado para armazenar e sincronizar
todos os dados. A importação firebase/app
, que configura a plataforma da API para
cada um dos diferentes serviços, é sempre necessária.
Muitas outras bibliotecas conhecidas, como lodash
, também permitem que os desenvolvedores
importem seletivamente diferentes partes dos pacotes. Sem fazer muito trabalho,
atualizar as importações de biblioteca em um aplicativo para incluir apenas o que está sendo usado
pode resultar em melhorias significativas no desempenho.
Embora o tamanho do pacote tenha sido reduzido bastante, ainda há mais trabalho a se fazer. 😈
Como remover pacotes desnecessários
Ao contrário do Firebase, a importação de partes da biblioteca moment
não é tão
fácil, mas talvez seja totalmente removida.
O aniversário de cada gatinho fofo é armazenado no formato Unix (milissegundos) no banco de dados do Firebase.
É um carimbo de data/hora de uma data e hora específicas representadas pelo número de milissegundos decorridos desde 1o de janeiro de 1970 à 00h00 UTC. Se a data e a hora atuais puderem ser calculadas no mesmo formato, uma pequena função para encontrar a idade de cada gatinho em semanas provavelmente poderá ser construída.
Como sempre, tente não copiar e colar ao acompanhar as informações aqui. Comece
removendo moment
das importações em src/index.js
.
import firebase from 'firebase/app';
import 'firebase/database';
import * as moment from 'moment';
No nosso banco de dados, há um listener de eventos que processa alterações de valor:
favoritesRef.on("value", (snapshot) => { ... })
Acima disso, adicione uma pequena função para calcular o número de semanas a partir de uma determinada data:
const ageInWeeks = birthDate => {
const WEEK_IN_MILLISECONDS = 1000 * 60 * 60 * 24 * 7;
const diff = Math.abs((new Date).getTime() - birthDate);
return Math.floor(diff / WEEK_IN_MILLISECONDS);
}
Nessa função, a diferença em milissegundos entre a data e a hora atuais (new Date).getTime()
e a data de nascimento (o argumento birthDate
, já em milissegundos) é calculada e dividida pelo número de milissegundos em uma única semana.
Por fim, todas as instâncias de moment
podem ser removidas no listener de eventos usando esta função:
favoritesRef.on("value", (snapshot) => { const { kitties, favorites, names, birthDates } = snapshot.val(); favoritesScores = favorites; kittiesList.innerHTML = kitties.map((kittiePic, index) => {const birthday = moment(birthDates[index]);return ` <li> <img src=${kittiePic} onclick="favKittie(${index})"> <div class="extra"> <div class="details"> <p class="name">${names[index]}</p><p class="age">${moment().diff(birthday, 'weeks')} weeks old</p><p class="age">${ageInWeeks(birthDates[index])} weeks old</p> </div> <p class="score">${favorites[index]} ❤</p> </div> </li> `}) });
Atualize o aplicativo e confira o painel Network mais uma vez.
O tamanho do nosso pacote foi reduzido pela metade outra vez!
Conclusão
Com este codelab, você terá uma boa compreensão de como analisar um pacote específico e por que pode ser tão útil remover pacotes não utilizados ou desnecessários. Antes de começar a otimizar um aplicativo com essa técnica, é importante saber que isso pode ser significativamente mais complexo em aplicativos maiores.
Em relação à remoção de bibliotecas não usadas, tente descobrir quais partes de um pacote estão sendo usadas e quais não estão. Para conferir um pacote misterioso que parece não estar sendo usado em nenhum lugar, confira quais dependências de nível superior podem precisar dele. Tente encontrar uma maneira de os separar.
Quando se trata de remover bibliotecas desnecessárias, tudo pode ser um pouco mais
complicado. É importante trabalhar em estreita colaboração com sua equipe e ver se há
potencial para simplificar partes da base de código. Remover moment
neste
aplicativo pode parecer a coisa certa a se fazer todas as vezes, mas e
se houvesse fusos horários e localidades diferentes que precisassem ser tratados? Ou
se houvesse manipulações de data mais complicadas? As coisas podem ficar muito
complicadas ao manipular e analisar datas/horas, e bibliotecas como moment
e date-fns
simplificam isso significativamente.
Tudo é uma compensação, e é importante avaliar se vale a complexidade e o esforço para lançar uma solução personalizada em vez de depender de uma biblioteca de terceiros.