简体   繁体   English

如何使用Service Worker缓存虚拟文件?

[英]How to use a Service Worker to cache a virtual file?

I am attempting to implement a service worker for a boilerplate project I'm working on ( https://github.com/jonnyasmar/gravity-bp feedback welcome!), but I've hit a snag :( 我正在尝试为我正在研究的样板项目实施服务工作者( https://github.com/jonnyasmar/gravity-bp反馈欢迎!),但我遇到了一个障碍:(

Problem: 问题:

I'm serving the index.html for this boilerplate virtually as an interpreted Twig template via ExpressJS. 我实际上是通过ExpressJS作为解释的Twig模板为该样板提供index.html的。 However, because I'm generating the service worker assets at build time and that is where I'm pointing it to the cacheable static assets, I can't figure out how to tell the service worker that I want it to cache the virtual index.html file served by ExpressJS at runtime. 但是,由于我是在构建时生成服务工作者资产的,因此我将其指向可缓存的静态资产,因此我无法弄清楚如何告诉服务工作者我要其缓存虚拟index.html ExpressJS在运行时提供的index.html文件。

My most successful attempts successfully cache all static assets (including the asset-manifest.json generated at build time), but will not cache a virtual index.html . 我最成功的尝试成功地缓存了所有静态资产(包括在构建时生成的asset-manifest.json ),但不会缓存虚拟index.html

If I convert it to a static html file, the service worker does successfully cache it. 如果我将其转换为静态html文件,则服务工作者确实会成功缓存它。

Please be sure to upvote this question to help get some visibility if you are interested in the answer! 如果您对答案感兴趣,请务必对这个问题进行投票,以帮助其获得更多的知名度!

Questions: 问题:

  1. Is there a way to correct my code to accomplish this? 有没有一种方法可以纠正我的代码来完成此任务?
  2. Is there anything wrong with doing it this way? 这样做有什么问题吗?
  3. If yes to #2, how would you recommend handling this and why? 如果对#2是肯定的,您将如何建议处理此问题,为什么?

See the full source on GitHub. 请参阅GitHub上的完整源代码。

Relevant code: 相关代码:

webpack.config.js : 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 : 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 : 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);
});

Within the sw-precache-webpack-plugin documentation it talks about using sw-precache options . sw-precache-webpack-plugin文档中,它讨论了使用sw-precache选项 The one you should investigate is the dynamicUrlToDependencies setting. 您应该研究的是dynamicUrlToDependencies设置。 See some of these links for more info: 有关更多信息,请参见以下链接:

For example, maybe start with this to test: 例如,也许从这里开始进行测试:

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

So really, you need to configure the sw-precache WebPack plugin to load a server rendered page as the navigateFallback route . 因此,实际上,您需要配置sw-precache WebPack插件以将服务器呈现的页面加载为navigationFallback route

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM