---
title: "Service Worker | grasys blog"
url: "https://blog.grasys.io/post/suwa/service-worker/"
description: "こんにちは、ATです。 運命のいたずらから Service Worker を触る機会があったので、その時経験した、あれやこれやを書いていきます。 前提：React TypeScript CRA Service Worker とは Worker Service Worker の前にまず Worker の話を。 Work…"
---

# Service Worker

-   ![](/_astro/noicon.CTHOhNiB_1HMs6A.webp)[AT](/authors/suwa/)
-   公開日：2021年6月21日
-   カテゴリー：[Tech](/categories/tech/)
-   タグ：[#JavaScript](/tags/javascript/)[#Service Worker](/tags/service-worker/)[#Worker](/tags/worker/)

![Service Worker](/_astro/og-image.DDSiu2Ny_XHpDd.webp)

こんにちは、ATです。

運命のいたずらから Service Worker を触る機会があったので、その時経験した、あれやこれやを書いていきます。

前提：React TypeScript CRA

## Service Worker とは

### Worker

Service Worker の前にまず Worker の話を。  
Worker とはなにかというと、バックグラウンドで実行されるタスクのことである。JavaScript では基本シングルスレッドで諸々の処理が行われる。そこにいわゆるマルチスレッドな処理を可能にする仕組みが Worker です。 Worker は別スレッドで動作しますが、マルチスレッドであることをあまり意識しないで使えるようになっています。とはいえそれは各種制約を課すことで実現されており、例えば、window オブジェクトのメソッドやプロパティに使えないものがあったり、DOMを直接操作することもできません。

Worker はインタフェースなので実態となるオブジェクトが数種類存在します。

・Dedicated Worker  
・Shared Worker  
・Service Worker

それぞれ、別スレッドで処理を実行するといったWorkerとしての基本は共通してますが、その他できることが違っています。全ての説明は割愛して今回は、Service Worker のみ紹介します。

#### Service Worker

Service Worker とは、基本的にウェブアプリケーション、ブラウザー、ネットワークの間に介在するプロキシサーバーのように振る舞います。サーバとの通信をキャッシュできPWAを実現するのに使用されてたりします。

Service Worker の他の Worker に対する利点として

・アプリのウィンドウがなくても処理ができる  
・プッシュ通知の対応  
・オリジンの違うwindowとやりとりできる  
と言ったものがあります。

また、下記の特徴があります。

・DOM 操作ができない  
　postMessage()でのメインスレッドにメッセージを送信しメインスレッド側で DOM 操作させることで一応 DOMに対して処理を行うことは可能らしいです。

・localStorageが使えない  
　データの保持には IndexedDB を使う

・https か localhost 上でしか動作しない  
　アプリの作りによってはデバッグで苦労する

## Service Worker 使ってみた

＊ここからの話はCRAを使ってるのが前提となります

### 有効化

index.tsx の

Plain textcontent\_copy

```
serviceWorker.unregister();
```

を

Plain textcontent\_copy

```
serviceWorker.register();
```

に変更する。  
これだけで Service Worker が起動しキャッシュを始めます。

### CRA(create-react-app) カスタマイズ

Service Worker のキャッシュをコントロールしたかったり、Service Worker に独自の処理を行わせるにはカスタマイズをほどこしてやらなければなりません。  
これをおこなうのに react-app-rewired を使用します。 react-app-rewired はWebpackの3,4系までの対応なので使用の際には注意が必要です。

・インストール

Plain textcontent\_copy

```
yarn install react-app-rewired
```

・Config-overrides.js をルートディレクトリに作成

Plain textcontent\_copy

```
const WorkboxWebpackPlugin = require('workbox-webpack-plugin')
module.exports = function override(config, env) {
  config.plugins = config.plugins.map(plugin => {
    if(plugin.constructor.name === 'GenerateSW') {
      return new WorkboxWebpackPlugin.InjectManifest({
        swSrc: './src/sw.js',
        swDest: 'service-worker.js'
      })
    }

    return plugin
  })

  return config
}
```

sw.jsを用意する。sw.js にコードを書くことでカスタマイズを行う。

・packeage.json 書き換え

Plain textcontent\_copy

```
"scripts": {
  "start": "react-app-rewired start",
  "build": "react-app-rewired build",
  "test": "react-app-rewired test",
  "eject": "react-scripts eject"
}
```

以上。 こうすることで、CRAでの設定を上書きし、独自の処理でカスタマイズできる。

#### TypeScript

Service Worker でTypeScript コードを実行する方法をいろいろ調べました。かなり苦しいが一応やれそうです。、やり方としては、別途トランスパイルしてjsファイルを作成しそれをimportして使います。正直微妙だが、他にやり方みつからず、、、ここで断念。

## 終わり

ここまで書いといてなんですが結局 Service Worker は使用しなかった。これは他にもいろいろ問題があったためで、必ずしも Service Worker だけに起因するモノではなかったです。今回のアプリのパスが特殊だったりとか、TypeScriptコードの使い回しがかなり困難だったり等ありまして、何より一番大きいのはDOM操作が直接できないということで、やりたい内容によってはかなり対応にコストがかかると感じました(あくまで今回のアプリでです)。postMessage()でメインスレッドとはやり取りできるので、DOM操作をメッセージで行うことはできるのですが、冗長だしそれに付帯する別の問題もあるしでやはり使いにくいとの結論になりました。ただ仕組みとしては色々面白いことができそうで、機会があれば使用してみたいと思ってます。

## この記事を書いた人

[![](/_astro/suwa.Dtk7B4h9_ZEmErx.webp)](/authors/suwa/)

### [AT](/authors/suwa/)

ATのプロフィールと執筆記事をご覧いただけます。

[プロフィールと記事一覧](/authors/suwa/)