如何使用 Service Worker 缓存虚拟文件?
How to use a Service Worker to cache a virtual file?
我正在尝试为我正在处理的样板项目实施服务工作者(https://github.com/jonnyasmar/gravity-bp 欢迎反馈!),但我遇到了障碍:(
问题:
我通过 ExpressJS 为这个样板提供 index.html
实际上是作为解释的 Twig 模板。但是,因为我在构建时生成服务工作人员资产,这就是我将其指向可缓存静态资产的地方,所以我无法弄清楚如何告诉服务工作人员我希望它缓存虚拟 index.html
ExpressJS 在运行时提供的文件。
我最成功的尝试成功缓存了所有静态资产(包括构建时生成的 asset-manifest.json
),但不会缓存虚拟 index.html
。
如果我将其转换为静态 html 文件,Service Worker 会成功缓存它。
如果您对答案感兴趣,请务必给这个问题点赞,以帮助提高知名度!
问题:
- 有没有办法更正我的代码来完成此操作?
- 这样做有什么问题吗?
- 如果对 #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);
});
在sw-precache-webpack-plugin documentation it talks about using sw-precache options内。您应该调查的一项是 dynamicUrlToDependencies 设置。有关详细信息,请参阅其中一些链接:
- https://github.com/GoogleChromeLabs/sw-precache/issues/156
- dynamicUrlToDependencies [Object⟨String,Buffer,Array⟨String⟩⟩]
比如,也许从这个开始测试:
dynamicUrlToDependencies: {
'/': 'MAGIC_STRING_HERE'
},
所以真的,你需要 configure the sw-precache WebPack plugin to load a server rendered page as the navigateFallback route。
我正在尝试为我正在处理的样板项目实施服务工作者(https://github.com/jonnyasmar/gravity-bp 欢迎反馈!),但我遇到了障碍:(
问题:
我通过 ExpressJS 为这个样板提供 index.html
实际上是作为解释的 Twig 模板。但是,因为我在构建时生成服务工作人员资产,这就是我将其指向可缓存静态资产的地方,所以我无法弄清楚如何告诉服务工作人员我希望它缓存虚拟 index.html
ExpressJS 在运行时提供的文件。
我最成功的尝试成功缓存了所有静态资产(包括构建时生成的 asset-manifest.json
),但不会缓存虚拟 index.html
。
如果我将其转换为静态 html 文件,Service Worker 会成功缓存它。
如果您对答案感兴趣,请务必给这个问题点赞,以帮助提高知名度!
问题:
- 有没有办法更正我的代码来完成此操作?
- 这样做有什么问题吗?
- 如果对 #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);
});
在sw-precache-webpack-plugin documentation it talks about using sw-precache options内。您应该调查的一项是 dynamicUrlToDependencies 设置。有关详细信息,请参阅其中一些链接:
- https://github.com/GoogleChromeLabs/sw-precache/issues/156
- dynamicUrlToDependencies [Object⟨String,Buffer,Array⟨String⟩⟩]
比如,也许从这个开始测试:
dynamicUrlToDependencies: {
'/': 'MAGIC_STRING_HERE'
},
所以真的,你需要 configure the sw-precache WebPack plugin to load a server rendered page as the navigateFallback route。