순서

  • 1. 지루한 pwa 설명
  • 2. 설치 및 개발
  • 3. 사용하면서 어려웠던 부분
  • 4. Push Notification
  • Q & A

1. 지루한 pwa 설명

  • 프로그레시브 - 모든 브라우저
  • 반응형 - 모든 디바이스
  • 연결 독립적 - Service Worker를 사용. 오프라인, 느린 네트워크에서도 작동
  • 앱과 유사 - 앱 셸 모드에서 작성. 앱 스타일의 동작
  • 최신 상태 - Service Worker에 업데이트 프로세스가 있음
  • 안전 - HTTPS를 통해 제공. (개발시 로컬은 http로 가능)
  • 검색 가능
  • 재참여 가능 - 푸시 알림과 같은 기능
  • 설치 가능 - 앱 스토어 사용 없이 설치
  • 링크 연결 가능 - URL을 통해 손쉽게 공유 및 설치

자세하게 알아보겠습니다

앱 셸이란?

애플리케이션 셸은 사용자 인터페이스를 지원하는 최소한의 HTML, CSS, 자바스크립트입니다. 애플리케이션 셸의 특징은 다음과 같습니다.

  • 로드 속도가 빠릅니다.
  • 캐시됩니다.
  • 콘텐츠를 동적으로 표시합니다.

참고 - https://support.google.com/partners/answer/7336597?hl=ko

앱 셸 디자인 시 고려해야할 점

  • 화면에 나와야 할 기본적인 구성
  • 필수적으로 들어와야 할 데이터
  • 필수적으로 들어와야 할 리소스 ex) 이미지, js, css...

그렇다면 Service Worker는?

Service Worker란 브라우저가 웹페이지와 별도로 백그라운드에서 실행하는 스크립트로서, 웹페이지나 사용자 상호작용 없이도 다양한 기능을 사용할 수 있게 합니다.

  • 설치
  • 푸시 알림
  • 백그라운드 동기화
  • 주기적 동기화 (업데이트)
  • 기타 등등...
참고 - https://support.google.com/partners/answer/7336697?hl=ko

2. 설치 및 개발


      $ vue init pwa my-project
      $ cd my-project
      $ npm i
    

그 다음은...

코딩 끝! 다음은 세팅...?

3. 사용하면서 어려웠던 부분

앱 개발 후 구글 pwa 튜토리얼 을 참고하여 세팅을 시작

3-1. Service Worker 등록하기

기본 방법

            // 기본적인 Service Worker 등록 방법 (자신의 코드)
            navigator.serviceWorker
              .register('./service-worker.js')
              .then(function() {
              console.log('Service Worker Registered');
            });
          

            // 기본적인 Service Worker 파일
            // self는 ServiceWorkerGlobal Scope를 지칭
            self.addEventListener('install', () => {
              self.skipWaiting()
            });

            self.addEventListener('activate', () => {
              self.clients.matchAll({ type: 'window' })
                .then(windowClients => {
                for (let windowClient of windowClients) {
                  // ...do someting!
                  windowClient.navigate(windowClient.url);
                }
              });
            });
          

3-1. Service Worker 등록하기

webpack.dev.conf.js 방법

          // in webpack.dev.conf.js
          ...
          plugins: [
            new HtmlWebpackPlugin({
              filename: 'index.html',
              template: 'index.html',
              inject: true,
              serviceWorkerLoader: `<script>
                ${fs.readFileSync(
                  path.join(__dirname,
                  './service-worker-dev.js'),
                  'utf-8'
                )}
              </script>`
            }),
            ...
          ]
        

          // in service-worker-dev.js
          self.addEventListener('install', () => {
            self.skipWaiting()
          });

          self.addEventListener('activate', () => {
            self.clients.matchAll({ type: 'window' })
            .then(windowClients => {
              for (let windowClient of windowClients) {
                // ...do someting!
                windowClient.navigate(windowClient.url);
              }
            });
          });
        

3-1. Service Worker 등록하기

webpack.prod.conf.js 방법

          // service worker caching in webpack.prod.conf.js
          plugins: [
            ...
            new SWPrecacheWebpackPlugin({
              cacheId: 'CACHE_ID',
              filename: 'service-worker.js',
              staticFileGlobs: ['dist/**/*.{js,html,css}'],
              minify: true,
              stripPrefix: 'dist/'
            })
            ...
          ]
        

          // in service-worker-prod.js
          ...
          window.addEventListener('load', function() {
            if ('serviceWorker' in navigator &&
                (window.location.protocol === 'https:'
                || isLocalhost)) {
              navigator.serviceWorker
              .register('service-worker.js')
              .then(function(registration) {
                // ...someting to do!
              }).catch(function(e) {
                console.error('err sw registration');
              });
            }
          });
          ...
        

3-2. Webpack 설정하기

SWPrecacheWebpackPlugin 라이브러리는 뭐하는 앤데...

=>기본적인 설정 내용에 따라 추가 Service Worker를 자동으로 생성해주는 놈!

3-2. Webpack 설정하기


            // API_CACHE_PATTERN은 캐시할 url
            new SWPrecacheWebpackPlugin({
              cacheId: 'seouldrinkerpwa',
              filename: 'service-worker.js',
              staticFileGlobs: ['dist/**/*.{js,html,css}'],
              minify: true,
              stripPrefix: 'dist/',
              runtimeCaching: [{
                urlPattern: API_CACHE_PATTERN,
                handler: 'networkFirst',
              }],
              importScripts: [
                'sw.js'
              ]
            }),
          

            // 이어서
            new CopyWebpackPlugin([
              {
                from: path.resolve(__dirname, '../static'),
                to: config.build.assetsSubDirectory,
                ignore: ['.*']
              },
              {
                from: path.resolve(__dirname, './sw.js'),
                to: '',
                ignore: ['.*']
              }
            ])
          

3-3. Service Worker 마무으리!

어후... 너무 복잡하다... 결론이 뭔데??

  1. 기본적으로 자신의 앱 코드 안에 서비스 워커를 등록 시켜주는 register 부분이 있어야 하고, 등록 될 Service Worker 파일이 있어야 한다.
  2. 그러나 vue-pwa-template 의 dev 버전에서는 register 부분이 따로 없다.
  3. Production 모드에서는 register 부분이 있으나, 서비스 워커를 자동으로 생성해주는 부분만 있다. (커스텀 시, 설정이 필요)
  4. Production 모드에서 사용하려면 webpack설정을 조금 바꿔줘야 하는데 문서가 쪼오금... 친절하진 않음.

4. Push Notification

사실 Vue에서의 세팅을 마치고 튜토리얼대로 하면 끝!
튜토리얼에서 알려주는대로 Service Worker에 Event를 등록해주세요.

Q&A

감사합니다.