DEV Community

Cover image for Nuxt 3 e PWA
Helton Carlos Brito Silva
Helton Carlos Brito Silva

Posted on

Nuxt 3 e PWA

Sabemos que existem muitas maneiras de desenvolver aplicativos. Hoje, vamos falar sobre PWA, uma abordagem muito interessante tanto em termos de tecnologia quanto em custo-benefício.

Vamos agitar as coisas neste exemplo usando o framework front-end Nuxt 3 com PWA! 🚀

1º Etapa - Instalação.

Entre no seu projeto feito em nuxt3 e instale o PWA Vite Plugin em seu projeto.

npm i @vite-pwa/nuxt -D 
Enter fullscreen mode Exit fullscreen mode

Adicione no nuxt.config.ts configure-o:

import { defineNuxtConfig } from 'nuxt/config'

export default defineNuxtConfig({
  modules: [
    '@vite-pwa/nuxt'
  ],
  pwa: {
    /* PWA options */
  }
})
Enter fullscreen mode Exit fullscreen mode

2º Etapa - Configurar manifest.

É hora de configurar seu projeto para PWA! Vou explicar detalhadamente cada parte que precisa ser configurada no seu projeto.

vamos começar com o manifest ele define critérios como resiliência, responsividade, conectividade e facilidade de instalação, permitindo que os desenvolvedores criem aplicativos que se comportem de forma semelhante a aplicativos nativos.

Dentro da pasta public crie uma pasta chamada manifest e adicione sua logo do projeto, as imagens devem conter o tamanho descrito dentro do sizes.

import { defineNuxtConfig } from 'nuxt/config'

export default defineNuxtConfig({
  modules: [
    '@vite-pwa/nuxt'
  ],
  pwa: {
   manifest: {
      name: 'nome do seu APP',
      short_name: 'nome simplificado do APP',
      theme_color: '#ffffff',
      start_url:'/',
      lang: 'pt-br',
      description: 'descrição do seu APP',
      screenshots: [
        {
          src: "manifest/home-screen.png",
          sizes: "320x320",
          type: "image/png",
          form_factor: "wide",
          label: "nome simplificado do APP"
        }
      ],
      icons: [
        {
          src: 'manifest/android-chrome-192x192.png',
          sizes: '192x192',
          type: 'image/png',
        },
        {
          src: 'manifest/android-chrome-512x512.png',
          sizes: '512x512',
          type: 'image/png',
        },
        {
          src: 'manifest/android-chrome-512x512.png',
          sizes: '512x512',
          type: 'image/png',
        },
      ],
    },
  }
})
Enter fullscreen mode Exit fullscreen mode

Uma dica super legal é usar o site: https://realfavicongenerator.net/
Ele facilita todo o processo de configurar as medidas necessárias para suas imagens, tudo a partir do logo principal do seu projeto.

3º Etapa - Configuração de strategies.

Na configuração de um PWA com o Workbox, existem duas estratégias principais que podem ser usadas para gerenciar o Service Worker:

generateSW: Esta estratégia é usada para gerar automaticamente um arquivo de Service Worker a partir de uma configuração simples. Ela é mais fácil de configurar, mas pode não oferecer o mesmo nível de controle que a estratégia injectManifest.

injectManifest: Esta estratégia permite injetar manualmente uma lista de arquivos para serem precacheados pelo Service Worker. Ela oferece um controle mais granular sobre quais arquivos são armazenados em cache, permitindo uma maior otimização do desempenho e uma experiência offline mais personalizada.

Neste exemplo iremos configurar na "mão" nossa estrategia para service workers, então usaremos o injectManifest.

Esta configuração indica que o método de injeção do manifest deve ser usado para gerar o service worker. O método de injeção do manifest permite que você adicione manualmente arquivos ao cache, dando mais controle sobre quais recursos são armazenados em cache. No exemplo dado, globPatterns define os padrões de arquivos que devem ser incluídos no cache. O padrão '*/.{js,css,html,png,svg,ico}' significa que o Workbox deve considerar todos os arquivos com extensões .js, .css, .html, .png, .svg e .ico para o cache.

import { defineNuxtConfig } from 'nuxt/config'

export default defineNuxtConfig({
  modules: [
    '@vite-pwa/nuxt'
  ],
  pwa: {
   strategies:'injectManifest',
   srcDir: 'service-worker',
   filename: 'sw.ts',
   registerType: 'autoUpdate',
   manifest: {
      name: 'nome do seu APP',
      short_name: 'nome simplificado do APP',
      theme_color: '#ffffff',
      start_url:'/',
      lang: 'pt-br',
      description: 'descrição do seu APP',
      screenshots: [
        {
          src: "manifest/home-screen.png",
          sizes: "320x320",
          type: "image/png",
          form_factor: "wide",
          label: "nome simplificado do APP"
        }
      ],
      icons: [
        {
          src: 'manifest/android-chrome-192x192.png',
          sizes: '192x192',
          type: 'image/png',
        },
        {
          src: 'manifest/android-chrome-512x512.png',
          sizes: '512x512',
          type: 'image/png',
        },
        {
          src: 'manifest/android-chrome-512x512.png',
          sizes: '512x512',
          type: 'image/png',
        },
      ],
    },
    workbox: {
      globPatterns: ['**/*.{js,css,html,png,svg,ico}'],
    },
    injectManifest: {
      globPatterns: ['**/*.{js,css,html,png,svg,ico}'],
    },
  }
})
Enter fullscreen mode Exit fullscreen mode

Criaremos a pasta chamada: service-worker com o arquivo: sw.ts

Dentro do arquivo sw.ts, iremos chamar o workbox é uma biblioteca JavaScript criada pelo google que simplifica o desenvolvimento de PWAs que utilizam Service Workers.

Basicamente esse código precacheAndRoute do Workbox serve para precachear e rotear os recursos listados em self.__WB_MANIFEST, que é uma lista gerada automaticamente pelo Workbox durante a compilação.

Colocaremos esse código:

/// <reference lib="WebWorker" />
/// <reference types="vite/client" />

import { cleanupOutdatedCaches, createHandlerBoundToURL, precacheAndRoute } from 'workbox-precaching'
import { clientsClaim } from 'workbox-core'
import { NavigationRoute, registerRoute } from 'workbox-routing'

declare let self: ServiceWorkerGlobalScope

precacheAndRoute(self.__WB_MANIFEST);

cleanupOutdatedCaches();

let allowlist: undefined | RegExp[]

if (import.meta.env.DEV)
  allowlist = [/^\/$/]

registerRoute(new NavigationRoute(
  createHandlerBoundToURL('/'),
  { allowlist },
))

self.skipWaiting();
clientsClaim();
Enter fullscreen mode Exit fullscreen mode

Observação: Como estamos usando typeScript para escrever seu service worker personalizado. Para resolver os tipos de service workers, basta adicionar WebWorkera no seu tsconfig.json arquivo:

{
  "compilerOptions": {
    "lib": ["ESNext", "DOM", "WebWorker"]
  }
}
Enter fullscreen mode Exit fullscreen mode

4º Etapa - Configurar client e devOptions.

Configurar client: Esse trecho de código está relacionado à configuração de um cliente, indica que o aplicativo deve exibir o prompt de instalação quando for detectado que ele pode ser instalado no dispositivo do usuário.

Configurar devOptions: Habilita as opções de desenvolvimento. Define a rota de fallback para a navegação. Isso significa que se o servidor não encontrar um recurso específico, ele retornará o arquivo especificado, neste caso, a rota raiz.

import { defineNuxtConfig } from 'nuxt/config'

export default defineNuxtConfig({
  modules: [
    '@vite-pwa/nuxt'
  ],
  pwa: {
   strategies:'injectManifest',
   srcDir: 'service-worker',
   filename: 'sw.ts',
   registerType: 'autoUpdate',
   manifest: {
      name: 'nome do seu APP',
      short_name: 'nome simplificado do APP',
      theme_color: '#ffffff',
      start_url:'/',
      lang: 'pt-br',
      description: 'descrição do seu APP',
      screenshots: [
        {
          src: "manifest/home-screen.png",
          sizes: "320x320",
          type: "image/png",
          form_factor: "wide",
          label: "nome simplificado do APP"
        }
      ],
      icons: [
        {
          src: 'manifest/android-chrome-192x192.png',
          sizes: '192x192',
          type: 'image/png',
        },
        {
          src: 'manifest/android-chrome-512x512.png',
          sizes: '512x512',
          type: 'image/png',
        },
        {
          src: 'manifest/android-chrome-512x512.png',
          sizes: '512x512',
          type: 'image/png',
        },
      ],
    },
    workbox: {
      globPatterns: ['**/*.{js,css,html,png,svg,ico}'],
    },
    injectManifest: {
      globPatterns: ['**/*.{js,css,html,png,svg,ico}'],
    },
    client: {
      installPrompt: true,
      periodicSyncForUpdates: 20,
    },
    devOptions: {
      enabled: true,
      suppressWarnings: true,
      navigateFallback: '/',
      navigateFallbackAllowlist: [/^\/$/],
      type: 'module',
    },
  }
})
Enter fullscreen mode Exit fullscreen mode

Quero agradecer a todos que chegaram ate aqui!
linkedin:
https://www.linkedin.com/in/helton-brito-856ba516b/

Top comments (2)

Collapse
 
robertofonsecabc profile image
Roberto Fonseca

Muito bom post!

Collapse
 
heltoncarlos profile image
Helton Carlos Brito Silva

Valeu Roberto!