1. ホーム
  2. javascript

[解決済み] DevToolsが装着されているため、タイムアウトタイマーによるService Workerの終了がキャンセルされた。

2022-02-06 12:06:37

質問

OS:Windows 10 Pro
webpackです。1.14.0
sw-precache-webpack-plugin: 0.9.1
sw-precache。5.0.0

そこで、サイトを立ち上げてしばらくは積極的に何もしないでいると、devToolsに上記の指定されたエラーメッセージが発生するのです。何らかの処理を行えば、このエラーは発生しません。

私のReactのコードは以下の通りです。

webpack.config.prod.js

var path = require('path');
var webpack = require('webpack');
var SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');

module.exports = {
  devtool: 'source-map',
  context: __dirname,
  entry: {
    main: path.resolve(__dirname, './client/app'),
  },
  output: {
    path: path.join(__dirname, '/public'),
    filename: 'bundle.js',
    publicPath: '/public/'
  },
  plugins: [
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': "'production'"
      }
    }),
    new webpack.optimize.UglifyJsPlugin({
      compressor: {
        warnings: false
      }
    }),
    new SWPrecacheWebpackPlugin(
      {
        cacheId: 'flamingoCity',
        filename: 'my-service-worker.js',
        stripPrefix: path.join(__dirname, 'public').replace(/\\/g,"/"),
        maximumFileSizeToCacheInBytes: 6194304,
        minify: true,
        runtimeCaching: [{
          handler: 'cacheFirst',
          urlPattern: /[.]mp3$/,
        }],
      }
    ),
  ],
  module: {
    loaders: [
    // js
    {
      test: /\.js$/,
      loaders: ['babel'],
      include: path.join(__dirname, 'client')
    },
    // CSS
    { 
      test: /\.styl$/, 
      include: path.join(__dirname, 'client'),
      loader: 'style-loader!css-loader!stylus-loader'
    }
    ]
  }
};

app.js

/*
  Import Dependencies
*/
import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { Router, Route, IndexRoute } from 'react-router'
import 'babel-polyfill';

/*
  Import Components
*/
import App from './components/App';
import Single from './components/Single';
import PhotoGrid from './components/PhotoGrid';

/* Import CSS */
import css from  './styles/style.styl';

/* Import our data store */
import store, { history } from './store';

/*
  Error Logging
*/

import Raven from 'raven-js';
import { sentry_url } from './data/config';
if(window) {
  Raven.config(sentry_url).install();
}

/*
  Register Service Worker
*/

if('serviceWorker' in navigator  && process.env.NODE_ENV === 'production') {
  navigator.serviceWorker.register('./my-service-worker.js').then(function(reg) {
  // updatefound is fired if my-service-worker.js changes.
  reg.onupdatefound = function() {
    // The updatefound event implies that reg.installing is set; see
    // https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#service-worker-container-updatefound-event
    var installingWorker = reg.installing;

    installingWorker.onstatechange = function() {
      switch (installingWorker.state) {
        case 'installed':
          if (navigator.serviceWorker.controller) {
            // At this point, the old content will have been purged and the fresh content will
            // have been added to the cache.
            // It's the perfect time to display a "New content is available; please refresh."
            // message in the page's interface.
            console.log('New or updated content is available.');
          } else {
            // At this point, everything has been precached.
            // It's the perfect time to display a "Content is cached for offline use." message.
            console.log('Content is now available offline!');
          }
          break;

        case 'redundant':
          console.error('The installing service worker became redundant.');
          break;
      }
    };
  };
  }).catch(function(e) {
    console.error('Error during service worker registration:', e);
  });
}

/*
  Rendering
  This is where we hook up the Store with our actual component and the router
*/
render(
  <Provider store={store}>
    { /* Tell the Router to use our enhanced history */ }
    <Router history={history}>
      <Route path="/" component={App}>
        <IndexRoute component={PhotoGrid} />
        <Route path="/view/:postId" component={Single}></Route>
      </Route>
    </Router>
  </Provider>,
  document.getElementById('root')
);

ここでの課題は何でしょうか?

解決方法は?

通常、アイドル状態のサービスワーカーは、不要なときにバックグラウンドでコードが実行されるのを防ぐため、最適化として積極的に強制終了されます。

Chromeは、DevToolsが開かれているかどうかを検出し、開かれている場合は、サービス ワーカーを自動的に停止しないようにする措置をとっています。これは、開発者が DevTools を使用している場合、サービス ワーカーの動作をデバッグまたは調査している可能性があり、サービス ワーカーを停止すると開発者の不満につながるという想定です。

サービスワーカーのライフタイム延長は、以前はサイレントで行われていましたが ここで説明されているように というメッセージが表示されます。

<ブロッククオート

タイムアウトタイマーによるサービスワーカーの終了がキャンセルされたのは DevToolsが添付されています。

はコンソールに記録され、サービスワーカーが通常であれば強制終了されるところ、DevTools が開いているために強制終了するジョブがキャンセルされたことを開発者に知らせます。

そんなことしてどうなるんだ、と思われるかもしれません。なぜわざわざ開発者に はなかった。 が起こるのでしょうか?

これを指摘する動機は、実際のユーザーが本番で遭遇するようなこと(サービスワーカーが繰り返し強制終了/再起動されるなど)が、このデバッグ環境では起きていないことを開発者に知ってもらうためです。これは、開発者がバグだらけのサービスワーカーコードを書いてしまい、その結果 グローバルステートの永続化に関する誤った仮定 . グローバルな状態が常に持続すると仮定したコードを書くのは簡単で、DevToolsを開いた状態で実行すると(サービスワーカーは決して殺されないので)動作しますが、本番では動作しないことがあります。