由于DevTools已连接,超时计时器终止Service Worker被取消了。

15

操作系统:Windows 10 Pro
webpack版本:1.14.0
sw-precache-webpack-plugin版本:0.9.1
sw-precache版本:5.0.0

我启动了网站,过了一段时间后,开发工具中就会出现如上所述的错误消息。如果进行某些操作,则不会出现此错误。

我的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')
);

这里的问题是什么?

2个回答

41

通常,空闲的 Service Worker 会被积极地终止以进行优化,以防止代码在后台运行时没有必要。

Chrome 会检测 DevTools 是否打开,并且如果打开了,则不会自动杀死 Service Worker。假设开发人员正在使用 DevTools,可能正在调试或以其他方式检查 Service Worker 的行为,并终止 Service Worker 将会使开发者感到沮丧。

延长 Service Worker 的生命周期曾经是悄无声息地完成的,但是如此处所述,在 Chrome 的最近几个版本中,控制台会记录以下信息:

由于附加了 DevTools,超时计时器取消了 Service Worker 的终止。

这样可以让开发者知道 Service Worker 通常会被终止,但由于 DevTools 打开而被取消了终止任务。

你可能会问,这有什么区别?为什么要让开发者知道某些事情没有发生?

指出这一点的动机是让开发者知道,正式用户会在生产环境中遇到的问题(即 Service Worker 被重复终止/重启)在此调试环境中没有发生。如果开发人员编写了有错误的 Service Worker 代码,而这些代码对全局状态的持久性进行了不正确的假设,那么这将会产生影响。 很容易编写出假定全局状态将始终存在并在 DevTools 打开时运行(因为 Service Worker 从未被杀死),然后在生产中无法运行的代码。


真的很好,他们加了这个消息 :- ) 现在我发现了这个主题,以及其他主题:https://dev59.com/hlkT5IYBdhLWcg3wRNet#38835274 —— 这将节省我很多时间,也许是几天时间: “通常,在服务工作者全局范围中任何事件处理程序之外的代码将在每次启动服务工作者线程(/进程)时运行…” - KajMagnus

0

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


4
你好,虽然你的代码可能解决了这个问题,但如果你能够包含一份代码说明(包括一些注释),并突出重要的片段以帮助他人理解你的答案,那将会很有帮助。 - Henry Woody

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接