【问题标题】:How to use a Service Worker to cache a virtual file?如何使用 Service Worker 缓存虚拟文件?
【发布时间】:2018-06-22 11:33:32
【问题描述】:

我正在尝试为我正在处理的样板项目实施服务工作者(https://github.com/jonnyasmar/gravity-bp 欢迎反馈!),但我遇到了障碍:(

问题:

我正在为这个样板提供index.html,实际上是通过 ExpressJS 解释的 Twig 模板。但是,因为我在构建时生成服务工作人员资产,并且我将其指向可缓存的静态资产,所以我无法弄清楚如何告诉服务工作人员我希望它缓存虚拟 @ 987654324@ ExpressJS 在运行时提供的文件。

我最成功的尝试成功缓存了所有静态资产(包括构建时生成的asset-manifest.json),但不会缓存虚拟的index.html

如果我将其转换为静态 html 文件,Service Worker 确实会成功缓存它。

如果您对答案感兴趣,请务必为这个问题点赞,以帮助提高知名度!

问题:

  1. 有没有办法更正我的代码以完成此操作?
  2. 这样做有什么问题吗?
  3. 如果对 #2 的回答是肯定的,您会建议如何处理这个问题以及为什么?

See the full source on GitHub.

相关代码:

webpack.config.js:

output: {
  filename: '[name].js',
    chunkFilename: '[chunkhash].js',
    path: path.resolve(__dirname, 'public'),
    publicPath: '/'
},
plugins: {
  new ManifestPlugin({
    fileName: 'asset-manifest.json',
  }),
  new SWPrecacheWebpackPlugin({
    cacheId: 'gravity-bp',
    dontCacheBustUrlsMatching: /\.\w{8}\./,
    filename: 'sw.js',
    minify: true,
    navigateFallback: 'index.html',
    stripPrefix: 'public/',
    swFilePath: 'public/sw.js',
    staticFileGlobs: [
      'public/index.html',
      'public/**/!(*map*|*sw*)',
    ],
  })
}

sw.ts:

const swUrl: string = 'sw.js';

export const register = (): void =>{
  if(process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator){
    const sw: ServiceWorkerContainer = navigator.serviceWorker;
    sw.register(swUrl).then(registration =>{
      registration.onupdatefound = (): any =>{
        const installer: ServiceWorker = registration.installing;
        installer.onstatechange = (): any =>{
          if(installer.state === 'installed'){
            if(sw.controller){
              console.log('New content available.');
            }else{
              console.log('Content cached for offline use.');
            }
          }
        };
      };
    }).catch((error) =>{
      console.error('Failed to register service worker:', error);
    });
  }
};

export const unregister = (): void =>{
  if('serviceWorker' in navigator){
    navigator.serviceWorker.ready.then(registration =>{
      registration.unregister();
    });
  }
};

server.ts:

import * as path from 'path';
const twig = require('twig').__express;
const express = require('express');
const compression = require('compression');

const pkg = require('../../package.json');
const version = pkg.version;

let app = express(),
  ip = '0.0.0.0',
  port = 3000,
  views = path.resolve('./src/views');

app.use(compression());
app.use(express.static('public'));
app.set('view engine', 'twig');
app.engine('.twig', twig);
app.set('views', views);

// Routes
app.get("*", function(req: any, res: any, next: any){
  // vars
  res.locals.version = version;

  res.render('index');
});

let server = app.listen(port, ip, function(){
  let host = server.address().address;
  let port = server.address().port;
  console.log('Gravity Boilerplate ready at http://%s:%s', host, port);
});

【问题讨论】:

    标签: reactjs express webpack service-worker server-side-rendering


    【解决方案1】:

    sw-precache-webpack-plugin 文档中,它谈到了使用sw-precache options。您应该调查的是 dynamicUrlToDependencies 设置。有关详细信息,请参阅其中一些链接:

    例如,也许可以从这个开始测试:

    dynamicUrlToDependencies: {
      '/': 'MAGIC_STRING_HERE'
    },
    

    真的,你需要configure the sw-precache WebPack plugin to load a server rendered page as the navigateFallback route

    【讨论】:

    • 如果依赖于 SO 网络之外的链接,则答案不完整。请添加详细信息,以便您的答案独立,即使链接被移动或删除。
    • 嗯,很有趣。我认为这是朝着正确方向迈出的一步。但是,我不确定如何将服务器端更改从 ExpressJS 挂钩到用于破坏缓存的 MAGIC_STRING,因为这是在构建时声明的。这里的想法是使用 Express 来指示 index.html 中的新内容,而不是像 jscss 包这样的文件更改。
    • 怎么样:const dateString = new Date(); dynamicUrlToDependencies: { '/': dateString }
    • 你就是男人!您的最新编辑将我提到其他 S/O 问题解决了它!如果你想看看我是如何实现的,我已经将我的代码推送到github.com/jonnyasmar/gravity-bp/tree/feature/service_worker(从webpack.config.json 的第47 行开始)。
    • 几天前我刚读了这篇文章,看到你的问题出现了——干杯! :-)
    猜你喜欢
    • 2016-02-23
    • 1970-01-01
    • 1970-01-01
    • 2016-10-28
    • 2017-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多