如何创建一个简单的服务工作者以将新项目添加到脱机缓存中?

时间:2017-05-11 02:04:53

标签: javascript webpack ecmascript-6 browser-cache service-worker

我想从一个简单的API中获取响应,使用它创建一系列URL(一个数组),然后我想将它们提供给服务工作者,并让它将每个条目添加到离线存储中。

对于后台,我对sw-precache(sw-precache-webpack-plugin),sw-toolbox和JavaScript有一些经验,尽管这种情况正在发生变化。目前有一个webpack + vue设置从很久以前构建的简单API中获取数据。

访问我网站的用户可能希望脱机使用一种或多种类型的内容 - 这可能需要将30个请求(30个单独的URL)添加到缓存中,最多可达4000多个。预计上限会随着时间的推移而增加。以我之前尝试过的方式运行Cache.addAll()会导致客户端崩溃 - 一次请求的请求太多。我认为importScripts选项可能是我需要的东西,但我不知道从哪里开始。如何编写一个脚本作为服务工作者的补充,我可以将数组发送到?

总结:

  • 使用webpack / vue
  • 熟悉sw-precache和sw-toolkit
  • 需要在一个用户请求中缓存数十到数千个页面
  • 想知道如何开发解决方案 问题,例如importScripts的示例代码片段,或者 另一个webpack插件,可以做到这一点,或其他替代方案 包含服务工作者的方法。

在开发代码中:https://laoadventist.info

用于将网址设置为cahce的简单API:https://laoadventist.info/api/r2

我想要缓存的单个示例API结果(单击一次按钮需要数十到数千个请求):... / api / d

更新

我能够提出一个有点功能的解决方案......它并不完美,或者在服务工作者中,但它确实有效。欢迎提出改进建议。

var temparray
var tempposition

let processCache = function (array, position) {
  if (typeof array === 'undefined') {
    array = []
  }
  if (array.length > 0) {
    let chunk = array.shift()
    temparray = array
    tempposition = position
    caches.open('testing')
      .then((cache) => { cache.addAll([chunk]) })
      .then(function () { processCache(temparray, tempposition) })
  }
}

3 个答案:

答案 0 :(得分:4)

选项1:使用webpack

Webpack用户可以从webpack-offline-plugin中受益,这些用户维护得很好并且能够很好地完成工作。但是,在运行时,您仍然需要为动态缓存编写一些代码。对于动态缓存,请参阅插件维护者的建议:here

选项2:制作自己的

在主捆绑文件中注册服务工作者

假设:您的服务工作者文件名为sw.js,它位于您网站的根文件夹中。

if ('serviceWorker' in navigator) {
  // Recommended to register onLoad
  window.addEventListener('load', function() {
    navigator.serviceWorker.register('/sw.js');
  });
}

sw.js内:安装静态

self.addEventListener('install', function(event) {
  self.skipWaiting();
  event.waitUntil(
    caches.open('static-files-v1').then(function(cache) {
      return cache.addAll(['/', 'someFile.js', 'someFile.css']);
    })
  );
});

sw.js内:获取已安装的静态

self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request).then(function(response) {
      return response || fetch(event.request)
    })
  );
});

更多高级步骤

sw.js内:缓存fetch

上的动态网址

fetch事件将通过HTTPS收听任何内容并将其提取到您的网站,请阅读我的评论以帮助理解该片段。

self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.open('dynamic-content-v1').then(function(cache) {
      // check if the requested URL is inside the dynamic-content-v1
      return cache.match(event.request).then(function (response) {
        // when found, respond with it.
        // when not found: return it as it is after taking a clone
        // and storing it, so next visit to the URL it will be there
        return response || fetch(event.request).then(function(response) {
          cache.put(event.request, response.clone());
          return response;
        });
      });
    })
  );
});

如果你有数以千计的页面,内容和图像,这种方法默认情况下不是一个很好的做法。您不希望膨胀用户并使用所有缓存存储配额。请考虑仅缓存首先要显示的内容并保持新鲜,因为您不希望发送过时的信息。

选项3和重要说明:

重要提示:您不需要SW将动态内容添加到缓存API。他们两个不同的东西。随意从框架组件\异步路由或其他任何内容中获取并添加到缓存API。

关于你的小提琴的建议和建议:

我不太确定我明白你在做什么100%。我可以看到一个递归函数但不确定为什么你需要它或者那里发生了什么。以下是有关如何从组件内部动态缓存的摘录:

// in case browser doesn't support cache
var URL_2_CACHE = '/content/important.html';
if (!('caches' in window)) return;
fetch(new Request(URL_2_CACHE)).then(function(response){
return caches.open('dynamic-cahce-v1').then(function(cache) {
    // DONE!
    return cache.put(URL_2_CACHE, response);
  });
});

现在HTML页面已存储在缓存中,SW将在下次请求时从那里获取它。

答案 1 :(得分:1)

你说你已经熟悉了sw-precache,所以我建议你使用sw-precache-webpack-plugin,因为你提到你正在使用。

使用runtimeCaching为您希望脱机使用的内容指定不同的缓存策略。

如果你的缓存太多,请使用maxEntries配置中的runtimeCaching,如下所示:

new SWPrecacheWebpackPlugin({
  runtimeCaching: [{
    urlPattern: /\/media\//,
    handler: 'cacheFirst',
    options: {
      cache: {
        maxEntries: 100,  // <-- limit entires to 100 before recycling
        name: 'media-cache'
      }
    }
  }]
})

答案 2 :(得分:-1)

如果您正在使用服务工作者,那么您只需要获取service-worker个对象并注册服务工作者文件。

我已经完成了一些代码:离线体验。 Here's该回购的代码,希望它有所帮助。

if ('serviceWorker' in navigator) {
  // registering the service worker file
  navigator.serviceWorker.register('./service-worker.js', {
    scope: './'                                                     // optional
  }).then(function (reg) {
    console.log('Service Worker registered successfully!');
  }).catch(function (err) {
    console.log('Service Worker failed to register', err);
  });
}

var name = 'simple nodexperts cache v2',
    filesToCache = [
      './index.html',
      './css/style.css',
      './script.js',
      './service-worker.js'
    ];

self.addEventListener('install', function (event) {
  console.log("installing");
  event.waitUntil(
    // opens cache
    // cache is an object which is available inside service-worker
    caches.open(name).then(function (cache) {
      return cache.addAll(filesToCache);
    })
  );
});

self.addEventListener('fetch', function (event) {
  console.log("fetching");
  event.respondWith(
    fetch(event.request).catch(function() {
      return caches.match(event.request);
    })
  );
});

您可以查看这些博客,这些博客非常好: