A Mainline é uma varejista de roupas on-line que oferece as maiores marcas de estilistas da moda. A empresa do Reino Unido confia na equipe de especialistas internos, combinada estrategicamente com os principais parceiros, para oferecer uma experiência de compra sem problemas para todos. Com presença de mercado em mais de 100 países, usando sete sites territoriais personalizados e um app, a Mainline vai continuar garantindo que a oferta de e-commerce esteja rivalizando com a concorrência.
Desafio
A meta da Mainline Menswear era complementar o site atual otimizado para dispositivos móveis com recursos progressivos que aderissem à visão "prioridade para dispositivos móveis", com foco em design e funcionalidade otimizados para dispositivos móveis, pensando em um mercado de smartphones em crescimento.
Solução
O objetivo era criar e lançar um PWA que complementasse a versão original otimizada para dispositivos móveis do site de vestuário masculino da Mainline e comparar as estatísticas com o app híbrido para dispositivos móveis, que está disponível para Android e iOS.
Depois que o app foi lançado e usado por uma pequena parte dos usuários da Mainline Menswear, foi possível determinar a diferença nas principais estatísticas entre a PWA, o app e a Web.
A abordagem da Mainline ao converter o site em um PWA foi garantir que o framework selecionado para o site (Nuxt.js, usando Vue.js) fosse à prova do futuro e permitisse que eles aproveitassem a tecnologia da Web em rápida evolução.
Resultados
139%
Mais páginas por sessão no PWA em comparação com a Web.
161%
Duração da sessão mais longa na PWA em comparação com a Web.
10%
Taxa de rejeição menor no PWA em comparação com a Web
12,5%
Maior valor médio do pedido na 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 usa o framework Nuxt.js para agrupar e renderizar o site, que é um aplicativo de página única (SPA).
Como gerar um arquivo de worker de serviço
Para gerar o service worker, a Mainline Menswear adicionou a configuração com uma implementação
personalizada do módulo nuxt/pwa
da caixa de trabalho.
A razão pela qual eles bifurcaram o módulo nuxt/pwa
era permitir que a equipe adicionasse mais personalizações ao
arquivo do service worker que não puderam ou tiveram 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 para 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 fim, a empresa agora pode acompanhar facilmente quantos usuários estão acessando 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 do ambiente de execução para navegação mais rápida
O armazenamento em cache para apps da Web é essencial para a otimização da velocidade da página e para oferecer uma melhor experiência a usuários recorrentes.
Para o armazenamento em cache na Web, há várias abordagens diferentes. A equipe está usando uma combinação do cache HTTP e da API Cache para armazenar recursos em cache no lado do cliente.
A API Cache oferece ao Mainline Menswear um controle mais refinado sobre os recursos em cache, permitindo que ele aplique 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
Para arquivos CSS e JS, a equipe escolheu armazená-los em cache e servi-los usando o
StaleWhileRevalidate
da estratégia Workbox. Essa estratégia permite que eles ofereçam todos os arquivos CSS e JS do Nuxt rapidamente,
o que aumenta significativamente a performance do site.
Ao mesmo tempo, os arquivos estão sendo 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',
);
Armazenamento em cache de fontes do Google
A estratégia de armazenamento em cache das Google Fonts depende de dois tipos de arquivo:
- A folha de estilo que contém as declarações
@font-face
. - Os arquivos de fonte subjacentes (solicitadas 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',
);
Armazenamento em cache de imagens
Para as imagens, a Mainline Menswear decidiu usar 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 sabem que não podem ocupar muito do armazenamento do dispositivo dos usuários. Com o Workbox, eles
adicionaram uma estratégia que armazena em cache imagens provenientes apenas do CDN com um máximo
de 60 imagens usando o
ExpirationPlugin
.
A 61a imagem (mais recente) solicitada substitui a 1a (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 imagem lida com o restante das imagens solicitadas pela origem. Essas imagens tendem a ser muito poucas e pequenas em toda a origem, mas, para garantir a 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,
}),
],
}),
);
Oferecer funcionalidade off-line
A página off-line é pré-armazenada em cache logo após a instalação e ativação do service worker. Para isso, eles criam 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á alguma incompatibilidade de revisão, atualizar e fornecer os
arquivos pré-armazenados em cache com uma estratégia CacheFirst
.
workbox.precaching.precacheAndRoute(PRECACHE);
Como lidar com navegações off-line
Depois que o service worker é ativado e a página off-line é pré-armazenada em cache, ele é usado para responder às solicitações de navegação off-line do usuário. Embora o app da Mainline Menswear seja um SPA, a página off-line só aparece depois que a página é recarregada, 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 forneceu um substituto para as 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
Gerar relatórios de instalações concluídas
Além do rastreamento de inicialização da tela inicial (com "start_url": "/?utm_source=pwa"
no manifesto
do aplicativo da Web), o app da Web também informa as instalações bem-sucedidas do app detectando o
evento appinstalled
em window
:
window.addEventListener('appinstalled', (evt) => {
ga('send', 'event', 'Install', 'Success');
});
Adicionar recursos de PWA ao seu site vai melhorar ainda mais a experiência dos clientes de comprar com você e será mais rápido de lançar no mercado do que um app [específico da plataforma].
Andy Hoyle, chefe de desenvolvimento
Conclusão
Para saber mais sobre apps da Web progressivos e como criá-los, acesse a seção de apps da Web progressivos no web.dev.
Para ler mais estudos de caso de apps da Web progressivos, acesse a seção de estudos de caso.