A Mainline é uma loja de roupas on-line que oferece as maiores marcas de estilistas do setor de moda. A empresa sediada no Reino Unido confia na equipe de especialistas internos, combinados estrategicamente com os principais parceiros, para fornecer uma experiência de compra simples para todos. Com presença de mercado em mais de 100 países por meio de sete sites territoriais personalizados e um app, a Mainline vai continuar garantindo que a oferta de e-commerce seja rival da concorrência.
Desafio
O objetivo da Mainline Menswear era complementar o atual site otimizado para dispositivos móveis com recursos progressivos que se aderissem à nossa visão "para dispositivos móveis", concentrando-se no design e na funcionalidade compatíveis com dispositivos móveis, considerando um mercado de smartphones em crescimento.
Solução
O objetivo era criar e lançar um PWA que complementasse a versão original compatível com dispositivos móveis do site da Mainline Menswear e, em seguida, comparar as estatísticas com o app híbrido para dispositivos móveis, disponível no Android e no iOS.
Depois que o app foi lançado e estava sendo usado por uma pequena seção de usuários masculinos da Mainline, eles conseguiram determinar a diferença nas principais estatísticas entre PWA, app e Web.
A abordagem que a Mainline adotou ao converter o site em um PWA foi garantir que o framework selecionado para o site (Nuxt.js, usando Vue.js) fosse preparado para o futuro e permitisse aproveitar a tecnologia da Web rápida.
Resultados
139%
Mais páginas por sessão no PWA do que na Web.
161%
Sessões mais longas no PWA em comparação com a Web.
10%
Menor taxa de rejeição no PWA em comparação com a Web
12,5%
de aumento no valor médio do pedido no PWA em comparação com a Web
55%
de aumento na taxa de conversão no PWA em comparação com a Web.
243%
de aumento na receita por sessão no PWA em comparação com a Web.
Aprofundamento técnico
A Mainline Menswear está usando o framework Nuxt.js para agrupar e renderizar o site, que é um aplicativo de página única (SPA).
Como gerar um arquivo de service worker
Para gerar o service worker, a Mainline Menswear adicionou a configuração usando uma
implementação personalizada do módulo nuxt/pwa
Workbox.
Eles bifurcaram o módulo nuxt/pwa
para permitir que a equipe adicionasse mais personalizações ao
arquivo do service worker que não conseguiam ou tinham problemas ao usar a versão padrão.
Uma dessas otimizações foi em torno da funcionalidade off-line do
site, como, por exemplo, veicular uma página off-line padrão e coletar análises off-line.
Anatomia do manifesto do app da Web
A equipe gerou um manifesto com ícones de diferentes tamanhos de ícones de apps para dispositivos móveis e outros detalhes
de apps da Web, como name
, description
e theme_color
:
{
"name": "Mainline Menswear",
"short_name": "MMW",
"description": "Shop mens designer clothes with Mainline Menswear. Famous brands including Hugo Boss, Adidas, and Emporio Armani.",
"icons": [
{
"src": "/_nuxt/icons/icon_512.c2336e.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#107cbb"
}
Depois de instalado, o app da Web pode ser iniciado na tela inicial sem que o navegador atrapalhe. Para isso, adicione o parâmetro display
ao arquivo de manifesto do app da Web:
{
"display": "standalone"
}
Por último, mas não menos importante, agora a empresa pode rastrear facilmente quantos usuários estão visitando o
app da Web pela tela inicial simplesmente anexando um parâmetro utm_source
no campo start_url
do
manifesto:
{
"start_url": "/?utm_source=pwa"
}
Armazenamento em cache no ambiente de execução para navegações mais rápidas
O armazenamento em cache para apps da Web é necessário para otimizar a velocidade da página e fornecer uma melhor experiência para usuários recorrentes.
Há algumas abordagens diferentes para o armazenamento em cache na Web. A equipe está usando uma combinação de cache HTTP e API Cache para armazenar recursos em cache no lado do cliente.
A API Cache oferece à Mainline Menswear um controle mais preciso sobre os recursos em cache, permitindo aplicar estratégias complexas a cada tipo de arquivo. Embora tudo isso pareça complicado e difícil de configurar e manter, o Workbox oferece uma maneira fácil de declarar essas estratégias complexas e facilita a manutenção.
Armazenamento em cache de CSS e JS
A equipe optou por armazenar arquivos CSS e JS em cache e exibi-los nesse cache usando a estratégia
StaleWhileRevalidate
do Workbox. Essa estratégia permite veicular todos os arquivos CSS e JS do Nuxt rapidamente, o que aumenta significativamente o desempenho do site.
Ao mesmo tempo, os arquivos são atualizados em segundo plano para a versão mais recente para a próxima visita:
/* sw.js */
workbox.routing.registerRoute(
/\/_nuxt\/.*(?:js|css)$/,
new workbox.strategies.StaleWhileRevalidate({
cacheName: 'css_js',
}),
'GET',
);
Como armazenar fontes do Google em cache
A estratégia de armazenamento em cache do Google Fonts depende de dois tipos de arquivo:
- A folha de estilo que contém as declarações
@font-face
. - Os arquivos de fontes subjacentes (solicitados na folha de estilo mencionada acima).
// Cache the Google Fonts stylesheets with a stale-while-revalidate strategy.
workbox.routing.registerRoute(
/https:\/\/fonts\.googleapis\.com\/*/,
new workbox.strategies.StaleWhileRevalidate({
cacheName: 'google_fonts_stylesheets',
}),
'GET',
);
// Cache the underlying font files with a cache-first strategy for 1 year.
workbox.routing.registerRoute(
/https:\/\/fonts\.gstatic\.com\/*/,
new workbox.strategies.CacheFirst({
cacheName: 'google_fonts_webfonts',
plugins: [
new workbox.cacheableResponse.CacheableResponsePlugin({
statuses: [0, 200],
}),
new workbox.expiration.ExpirationPlugin({
maxAgeSeconds: 60 * 60 * 24 * 365, // 1 year
maxEntries: 30,
}),
],
}),
'GET',
);
Como armazenar imagens em cache
No caso das imagens, a Mainline Menswear decidiu escolher duas estratégias. A primeira estratégia se aplica a todas as imagens provenientes da CDN, que geralmente são imagens de produtos. As páginas têm muitas imagens, então eles estão conscientes de não ocupar muito do armazenamento do dispositivo dos usuários. Então, usando o Workbox, foi adicionada uma estratégia que é armazenar em cache imagens provenientes apenas da CDN com um máximo de 60 imagens usando ExpirationPlugin
.
A 61a (mais recente) imagem solicitada substitui a primeira (mais antiga) para que no máximo 60 imagens de produtos sejam armazenadas em cache a qualquer momento.
workbox.routing.registerRoute(
({ url, request }) =>
url.origin === 'https://mainline-menswear-res.cloudinary.com' &&
request.destination === 'image',
new workbox.strategies.StaleWhileRevalidate({
cacheName: 'product_images',
plugins: [
new workbox.expiration.ExpirationPlugin({
// Only cache 60 images.
maxEntries: 60,
purgeOnQuotaError: true,
}),
],
}),
);
A segunda estratégia de imagens processa o restante das imagens solicitadas pela origem. Essas imagens tendem a ser muito poucas e pequenas em toda a origem, mas, por questões de segurança, o número dessas imagens em cache também é limitado a 60.
workbox.routing.registerRoute(
/\.(?:png|gif|jpg|jpeg|svg|webp)$/,
new workbox.strategies.StaleWhileRevalidate({
cacheName: 'images',
plugins: [
new workbox.expiration.ExpirationPlugin({
// Only cache 60 images.
maxEntries: 60,
purgeOnQuotaError: true,
}),
],
}),
);
Fornecimento de funcionalidade off-line
A página off-line é pré-armazenada em cache logo após o service worker ser instalado e ativado. Isso é feito criando uma lista de todas as dependências off-line: o arquivo HTML off-line e um ícone SVG off-line.
const OFFLINE_HTML = '/offline/offline.html';
const PRECACHE = [
{ url: OFFLINE_HTML, revision: '70f044fda3e9647a98f084763ae2c32a' },
{ url: '/offline/offline.svg', revision: 'efe016c546d7ba9f20aefc0afa9fc74a' },
];
A lista de pré-cache é alimentada no Workbox, que cuida de todo o trabalho pesado de adicionar os
URLs ao cache, verificar se há incompatibilidade de revisão, atualizar e disponibilizar os
arquivos pré-armazenados em cache com uma estratégia CacheFirst
.
workbox.precaching.precacheAndRoute(PRECACHE);
Como gerenciar navegações off-line
Depois que o service worker é ativado e a página off-line é pré-armazenada em cache, ela é usada para responder às solicitações de navegação off-line do usuário. Embora o app da Web da Mainline Menswear seja um SPA, a página off-line é mostrada somente depois que a página é atualizada, o usuário fecha e reabre a guia do navegador ou quando o app da Web é iniciado na tela inicial enquanto está off-line.
Para isso, a Mainline Menswear ofereceu um substituto para solicitações
NavigationRoute
com falha com a página off-line pré-armazenada em cache:
const htmlHandler = new workbox.strategies.NetworkOnly();
const navigationRoute = new workbox.routing.NavigationRoute(({ event }) => {
const request = event.request;
// A NavigationRoute matches navigation requests in the browser, i.e. requests for HTML
return htmlHandler.handle({ event, request }).catch(() => caches.match(OFFLINE_HTML, {
ignoreSearch: true
}));
});
workbox.routing.registerRoute(navigationRoute);
Demonstração
Relatórios de instalações concluídas
Além do acompanhamento de inicialização da tela inicial (com "start_url": "/?utm_source=pwa"
no manifesto
do app da Web), o app da Web também registra instalações bem-sucedidas ao detectar o
evento appinstalled
em window
:
window.addEventListener('appinstalled', (evt) => {
ga('send', 'event', 'Install', 'Success');
});
A adição de recursos de PWA ao seu site melhora ainda mais a experiência dos clientes ao comprar com você, além de facilitar o lançamento de um app [específico da plataforma].
Andy Hoyle, diretor de desenvolvimento
Conclusão
Para saber mais sobre Progressive Web Apps e como criá-los, acesse a seção Progressive Web Apps em web.dev.
Para ler mais estudos de caso de Progressive Web Apps, navegue até a seção de estudos de caso.