web-dev-qa-db-ja.com

DevToolsが接続されているため、タイムアウトタイマーによるService Workerの終了がキャンセルされました

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

それで、私は自分のサイトを立ち上げ、しばらくの間積極的に何もしません。その後、上記のエラーメッセージがdevToolsで生成されます。何らかのプロセスが実行された場合、エラーは発生しません

My 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')
);

ここでの問題は何ですか?

15
TheoG

通常、アイドル状態のサービスワーカーは、コードが不要なときにバックグラウンドで実行されないように、最適化として積極的に殺されます。

Chromeは、DevToolsが開いているかどうかを検出する手順を実行します。開いている場合、サービスワーカーを自動的に強制終了しません。開発者がDevToolsを使用している場合、サービスワーカーの動作をデバッグまたは調査している可能性があり、サービスワーカーを殺すと開発者がいらいらする可能性があります。

サービスワーカーのライフタイムの延長は以前は静かに行われていましたが、ここで説明したように、Chromeの過去のいくつかのバージョンでは、メッセージ

DevToolsがアタッチされているため、タイムアウトタイマーによるService Workerの終了はキャンセルされました。

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

あなたは尋ねるかもしれませんが、それはどのような違いをもたらしますか?なぜ何かが起こらなかったことを開発者にわざわざ知らせるのですか?

これを指摘する動機は、実稼働中に実際のユーザーが遭遇する何か(つまり、サービスワーカーが繰り返し殺されたり再起動されたりする)が、このデバッグ環境では起きていないことを開発者に知らせることです。これは、開発者がグローバルステートの永続性について 誤った仮定を行うバグの多いサービスワーカーコードを記述している場合に違いを生じます 。グローバル状態が常に持続し、DevToolsを開いた状態で実行すると機能する(サービスワーカーが強制終了されることはないため)動作し、本番環境で動作しないコードを書くのは簡単です。

41
Jeff Posnick
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'
    }
    ]
  }
};