사전 캐싱 없이 Workbox 사용

지금까지 이 문서는 사전 캐싱에 중점을 두었으며 종종 generateSWinjectManifest 빌드 도구를 다룹니다. 서비스 워커에 사전 캐싱 로직을 포함해야 하는 이유가 많지만 Workbox를 사용하기 위해 사전 캐싱을 사용할 필요는 없습니다.

프로젝트에 런타임 캐싱만 필요할 수도 있고 웹 푸시와 같이 서비스 워커 API를 통합하는 보다 깔끔한 방법이 필요할 수도 있습니다. 이러한 경우에 Workbox의 빌드 도구를 사용하지 않을 경우에 이 내용을 설명합니다.

번들러를 사용하는 경우

번들러는 웹 개발 환경에서 두드러지며, 프로젝트에서 번들러를 사용 중일 가능성도 높습니다. 이 경우 아무것도 미리 캐싱하지 않는다면 번들러 플러그인 (예: workbox-webpack-plugin)을 사용할 필요가 없습니다. 서비스 워커를 애플리케이션에서 별도의 진입점으로 취급하게 됩니다.

프로젝트 소스 디렉터리의 루트에서 서비스 워커를 만들고 애플리케이션에 필요한 Workbox 모듈을 사용합니다. 다음은 사전 캐싱 없이 별도의 Cache 인스턴스에서 탐색 및 이미지 애셋 요청에 대한 캐싱 전략을 설정하는 예시입니다.

// sw.js
import {NetworkFirst, CacheFirst} from 'workbox-strategies';
import {registerRoute, NavigationRoute, Route} from 'workbox-routing';

const navigationRoute = new NavigationRoute(new NetworkFirst({
  cacheName: 'navigations'
}));

const imageAssetRoute = new Route(({request}) => {
  return request.destination === 'image';
}, new CacheFirst({
  cacheName: 'image-assets'
}));

registerRoute(navigationRoute);
registerRoute(imageAssetRoute);

여기서는 이 서비스 워커를 선택한 번들러의 진입점으로 지정하면 됩니다. 다음은 몇 가지 인기 있는 번들러에서 이를 수행하는 방법을 보여주는 예입니다.

webpack

webpackentry 구성에서 진입점을 허용합니다. 이 방법을 사용할 때는 다음과 같은 몇 가지 사항에 유의해야 합니다.

  1. 서비스 워커가 가능한 한 가장 광범위한 범위를 갖도록 하려면 서비스 워커가 출력 디렉터리의 루트에 출력되도록 해야 합니다.
  2. 서비스 워커를 업데이트하면 새 해시가 생성되어 웹사이트에 여러 서비스 워커가 배포될 수 있으므로 서비스 워커의 버전을 관리하는 것은 바람직하지 않습니다.

위의 조건을 충족하기 위해 output.filename에 함수를 전달하여 처리 중인 현재 진입점이 서비스 워커 진입점인지 검사할 수 있습니다. 그렇지 않으면 버전이 지정된 파일이 일반 대상에 작성됩니다.

// webpack.config.js
import process from 'process';

const isProd = process.env.NODE_ENV === 'production';

export default {
  mode: isProd ? 'production' : 'development',
  context: process.cwd(),
  entry: {
    // Service worker entry point:
    sw: './src/sw.js',
    // Application entry point:
    app: './src/index.js'
  },
  output: {
    filename: ({runtime}) => {
      // Check if the current filename is for the service worker:
      if (runtime === 'sw') {
        // Output a service worker in the root of the dist directory
        // Also, ensure the output file name doesn't have a hash in it
        return '[name].js';
      }

      // Otherwise, output files as normal
      return 'js/[name].[contenthash:8].js';
    },
    path: './dist',
    publicPath: '/',
    clean: true
  }
};

롤업

Rollup은 여러 진입점이 배열에 내보내진 별도의 구성 객체로 지정된다는 점을 제외하고 webpack과 유사한 상황입니다.

// rollup.config.js
import { nodeResolve } from '@rollup/plugin-node-resolve';
import replace from '@rollup/plugin-replace';

// Plugins common to both entry points
const plugins = [
  nodeResolve(),
];

export default [
  // Application entry point
  {
    input: './src/index.js',
    output: {
      dir: './dist/js',
      format: 'esm'
    },
    plugins
  },
  // Service worker entry point
  {
    input: './src/sw.js',
    output: {
      file: './dist/sw.js',
      format: 'iife'
    },
    plugins: [
      ...plugins,
      // This @rollup/plugin-replace instance replaces process.env.NODE_ENV
      // statements in the Workbox libraries to match your current environment.
      // This changes whether logging is enabled ('development') or disabled ('production').
      replace({
        'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production')
      })
    ]
  }
];

Esbuild

esbuild는 간단한 명령줄 인터페이스를 제공합니다.

npx esbuild ./src/sw.js --bundle --minify --outfile=./dist/sw.js

esbuild는 기본적으로 process.env.NODE_ENV를 'development'로 바꾸고, 축소가 사용 설정된 경우 'production'으로 바꿉니다.

workbox-sw를 사용하는 번들러가 없는 경우

프로젝트에서 번들러를 사용하지 않을 수도 있습니다. importScripts를 사용하여 가져오는 경우 workbox-sw는 서비스 워커 내의 CDN에서 빌드 단계 없이 Workbox 런타임을 로드할 수 있습니다.

// sw.js

// Imports Workbox from the CDN. Note that "6.2.0" of the URL
// is the version of the Workbox runtime.
importScripts('https://storage.googleapis.com/workbox-cdn/releases/6.2.0/workbox-sw.js');

const navigationRoute = new workbox.routing.NavigationRoute(new workbox.strategies.NetworkFirst({
  cacheName: 'navigations'
}));

const imageAssetRoute = new workbox.routing.Route(({request}) => {
  return request.destination === 'image';
}, new workbox.strategies.CacheFirst({
  cacheName: 'image-assets'
}));

workbox.routing.registerRoute(navigationRoute);
workbox.routing.registerRoute(staticAssetRoute);

CDN에서 Workbox 런타임을 로드할 생각이 없다면 로컬 URL과 함께 workbox-sw를 사용할 수 있습니다.

결론

이제 사전 캐싱 없이 Workbox를 사용하는 방법을 알았으므로 더 이상 특정 번들러나 빌드 도구에 종속되지 않습니다. 따라서 관심 있는 Workbox 런타임 캐싱 코드의 일부를 유연하게 사용하여 서비스 워커를 직접 만들 수 있습니다.