본문 바로가기
pwa

[pwa] quasar에서 pwa모드 간단하게 추가하기

by 냉면돈가스 2024. 12. 3.

(작성중...)

@quasar/cli@2.4.1 기준

 

quasar를 이용하면 ssr, pwa등 간단하게 빌드모드를 추가할 수 있다...

짧은 시간내에 pwa를 설치하고싶으면 사용하기 좋을듯

https://quasar.dev/quasar-cli-vite/developing-pwa/introduction

 

What is a PWA | Quasar Framework

(@quasar/app-vite) Introduction on what a Progressive Web App is and how it can be configured in a Quasar app.

quasar.dev

 

명령어는 "quasar build -m pwa" 로 입력하면 spa모드와 똑같이 dist안에 pwa폴더가 생기고,

호스팅 폴더에 위치시키면 완료.

삼성 브라우저 등으로 웹 주소 입력시 설치 버튼이 생긴다.

 

포스팅 할내용은 (quasar 기준)

 - pwa 모드로 빌드시 관련 설정 폴더, 폴더 아래에 파일들이 생기는데 이들이 어떤역할을 하는지 알아보기

 - 브라우저로 진입시 즉시 pwa앱 설치 메시지 띄워주기 기능구현

 - api error등 특정 에러 시 pwa앱으로 에러 알림 띄워주기 기능구현

 - pwa 모드 빌드시 디버깅 유무 차이


* 서비스 워커란?

 

웹에서 제공되던 js의 웹스레드와 비슷한 개념으로

js의 스레드와 다른 영역으로 pwa의 스레드.

 

브라우저에서 닫혀있어도 백그라운드에서 작동할 수 있고,

인터넷 연결이 끊겨있는 오프라인 상황에서도 캐싱 기능을 통해 동작할 수 있음

서비스 워커의 특성으로 백그라운드에서 돌아가면서 사용자의 디바이스에 알림을 주는등 가능하다고 함

보안상의 이유로 https, local 환경에서만 작동함


pwa 모드 빌드시 파일 구성

 

- manifest

  pwa 앱의 메타데이터 정의 파일

  아이콘,색상 등 앱설치/로드 시 화면을 표현하는데 사용함

 

- pwa-flag.d.ts

  이 파일은 퀘이사 문서에 따로 내용이 없다.

  그냥 quasar앱에서 pwa 기능 활성화 되었단걸 인식하기 위한 파일인듯 

 

- custom-service-worker.js

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

self.skipWaiting()
// 준비된 서비스워커를 실행
clientsClaim()
// 서비스 워커가 클라이언트(pwa앱)을 제어하도록 설정함

// Use with precache injection
precacheAndRoute(self.__WB_MANIFEST)
// 빌드 과정에서 생성된 manifest 파일을 미리 캐싱함
// manifest 이외에도 기타 자원들을 미리 캐싱하여 오프라인 상태에서 사용할 수 있음

cleanupOutdatedCaches()
// 이번 버전의 캐시를 정리하여 사용자가 최신 리소스를 사용하도록 함

// Non-SSR fallback to index.html
// Production SSR fallback to offline.html (except for dev)
if (process.env.MODE !== 'ssr' || process.env.PROD) {
  registerRoute(
    new NavigationRoute(
      createHandlerBoundToURL(process.env.PWA_FALLBACK_HTML),
      { denylist: [/sw\.js$/, /workbox-(.)*\.js$/] }
    )
  )
}

// registerRoute : 내비게이션 요청을 처리하는 라우트 생성
// new NavigationRoute함수의 반환값 형식으로 registerRoute에 전달하는 듯
// new NavigationRoute에 들어갈 인자로는 
// 1. "createHandlerBoundToURL(process.env.PWA_FALLBACK_HTML)"
// 2.  { denylist: [/sw\.js$/, /workbox-(.)*\.js$/] } 
// 가 있음
// createHandlerBoundToURL은 오프라인 상황(인터넷 끊김)에서 
// 주어진 url 요청에 대한 응답을 제공하는데 실패했을시, 반환되는 자원임
// denylist에 들어가는 것들은 서비스 워커의 기능에 영향을 미치는 특정파일들이며 캐싱에서 제외함

 

요약하자면 캐시를 활용한 오프라인 로직을 작성해

사용자가 오프라인에서도 어느정도 앱을 이용할 수 있도록 하는 파일인듯함.

요 기능은 추후에 공부하여 사용하면 좋을듯

내가 이번에 포스팅 할 내용은 주로 알림기능이니..

register-service-worker.js에 내용을 먼저 공부할듯

 

spa 특성상 그때그때 api를 이용해 데이터를 받아오는데...

오프라인 상황에서는 api이용이 어려울 거 같고

데이터를 로컬스토리지와 같은 저장소에 담지않아도 캐싱이 가능한가?

결국 정적 자원만 보여줘야하나?

 

보통의 상황에선 "인터넷이 안되는상황에서도 어느정도 잘되게 해주세요"

요구사항이 적을테니... 필요한 분들만 추가로 공부하시고

저는 나중에 간단하게 공부할게요

 

- register-service-worker.js

import { register } from "register-service-worker";

// The ready(), registered(), cached(), updatefound() and updated()
// events passes a ServiceWorkerRegistration instance in their arguments.
// ServiceWorkerRegistration: https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration

register(process.env.SERVICE_WORKER_FILE, {
  // The registrationOptions object will be passed as the second argument
  // to ServiceWorkerContainer.register()
  // https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/register#Parameter

  // registrationOptions: { scope: './' },

  ready(/* registration */) {
    // console.log('Service worker is active.')
  },

  registered(/* registration */) {
    // console.log('Service worker has been registered.')
  },

  cached(/* registration */) {
    // console.log('Content has been cached for offline use.')
  },

  updatefound(/* registration */) {
    // console.log('New content is downloading.')
  },

  updated(/* registration */) {
    // console.log('New content is available; please refresh.')
  },

  offline() {
    // console.log('No internet connection found. App is running in offline mode.')
  },

  error(/* err */) {
    // console.error('Error during service worker registration:', err)
  },
});

 

서비스 워커의 상태변화에 따라 호출되는것처럼 보인다.

예를 들어 ready 핸들러는 서비스 워커가 활성화되었을때 호출되는듯

 

푸시 알림 등 서비스워커의 이벤트 핸들링을 할때 사용하면 좋을듯.

내가 하려던건 특정상황이 일어났을때 모바일에 푸시알림을 주려던거니,

이 파일에서 테스트를 하면 될거같음


핸들러들 테스트를 하려하는데,

https 서버를 쓰거나 로컬에서 가능함.

모바일에서 서버를 실행할 순 없으니 ngrok라는 무료 임시 https 프로토콜 체인저를 사용해 테스트

 

https://download.ngrok.com/windows

 

Download ngrok

Download ngrok

download.ngrok.com

windows용 ngrok이나 npm에서 다운로드 후,

ngrok 회원가입하면 나오는 토큰키를 세팅한다.

ngrok config add-authtoken

 

실행문장은 "ngrok http 8080"

당연히 포트는 당신이 https로 변환할 앱이 열려있는 포트 입력

 

24.12.04

테스트 예정

pc로컬 환경에선 알림나오는거 체크함

모바일에서 pwa 설치 후 앱 오픈시 알림 똑같이 뜨면 성공

 

- 모바일 환경 ready handler 테스트

// register-service-worker.js

if ("Notification" in window && navigator.serviceWorker) {
  Notification.requestPermission().then(permission => {
    if (permission === "granted") {
      console.log("Notification permission granted.");
    } else {
      console.log("Notification permission denied.");
    }
  });
}

self.addEventListener("push", event => {
  const title = "Welcome to the App!";
  const options = {
    body: "You have successfully entered the app.",
    icon: "icons/icon-192x192.png", // 알림 아이콘
  };

  event.waitUntil(self.registration.showNotification(title, options));
});

navigator.serviceWorker.ready.then(registration => {
  registration.showNotification("Welcome!", {
    body: "You have entered the app.",
    icon: "icons/icon-192x192.png",
  });
});

quasar의 pwa 기본문장구조밑에 추가로 그냥 간단하게 작성
ready상태일때 알림을 제공한다.

 

- 모바일 환경 api error시 알림 테스트

if ("Notification" in window && navigator.serviceWorker) {
  Notification.requestPermission().then(permission => {
    if (permission === "granted") {
      console.log("Notification permission granted.");
    } else {
      console.log("Notification permission denied.");
    }
  });
}

self.addEventListener("push", event => {
  const title = "Welcome to the App!";
  const options = {
    body: "You have successfully entered the app.",
    icon: "icons/icon-192x192.png", // 알림 아이콘
  };

  event.waitUntil(self.registration.showNotification(title, options));
});

navigator.serviceWorker.ready.then(registration => {
  globalThis.registration = registration;
  registration.showNotification("ready!", {
    body: "You have ready the app.",
    icon: "icons/icon-192x192.png",
  });
  globalThis.pwaNotification = () => {
    globalThis.registration.showNotification("ready!", {
      body: "You have ready the app.",
      icon: "icons/icon-192x192.png",
    });
  };
});

이런식으로 전역객체에 registration와 showNotification함수기능을 넣어
api error등 특정상황이 있을때 알림기능 주기 가능

pwa 모드 빌드시 디버깅 유무 차이

 

https://quasar.dev/quasar-cli-vite/developing-pwa/build-commands#building-for-production

 

PWA Build Commands | Quasar Framework

(@quasar/app-vite) The Quasar CLI list of commands when developing or building a Progressive Web App.

quasar.dev

위 링크엔 명령어는 소개되어있는데 명령어 유무에 따른 차이는 따로 소개되어있지 않았음..

그래서 테스트 해볼려고했는데

pwa 테스트를 위해서는 모바일 디바이스 설정에서 개발자 모드를 킨 후, usb를 통해 pc와 연동해야함..

usb가 일단 없어서 보류

댓글