1
+ const toCache = require ( 'static-to-cache' ) ( ) ;
2
+ const version = require ( 'static-version' ) ( ) ;
3
+ const revGet = require ( 'static-rev-get' ) ;
4
+
5
+ const staticCacheName = `static-${ version } ` ;
6
+
7
+ addEventListener ( 'install' , event => {
8
+ skipWaiting ( ) ;
9
+
10
+ event . waitUntil ( async function ( ) {
11
+ const cache = await caches . open ( staticCacheName ) ;
12
+ await cache . addAll ( toCache ) ;
13
+ } ( ) ) ;
14
+ } ) ;
15
+
16
+ addEventListener ( 'activate' , event => {
17
+ event . waitUntil ( async function ( ) {
18
+ const keys = await caches . keys ( ) ;
19
+ await Promise . all (
20
+ keys . map ( key => {
21
+ if ( key !== staticCacheName ) return caches . delete ( key ) ;
22
+ } )
23
+ ) ;
24
+ } ( ) ) ;
25
+ } ) ;
26
+
27
+ class IdentityStream {
28
+ constructor ( ) {
29
+ let readableController ;
30
+ let writableController ;
31
+
32
+ this . readable = new ReadableStream ( {
33
+ start ( controller ) {
34
+ readableController = controller ;
35
+ } ,
36
+ cancel ( reason ) {
37
+ writableController . error ( reason ) ;
38
+ }
39
+ } ) ;
40
+
41
+ this . writable = new WritableStream ( {
42
+ start ( controller ) {
43
+ writableController = controller ;
44
+ } ,
45
+ write ( chunk ) {
46
+ readableController . enqueue ( chunk ) ;
47
+ } ,
48
+ close ( ) {
49
+ readableController . close ( ) ;
50
+ } ,
51
+ abort ( reason ) {
52
+ readableController . error ( reason ) ;
53
+ }
54
+ } ) ;
55
+ }
56
+ }
57
+
58
+ async function streamArticle ( event , url ) {
59
+ const includeUrl = new URL ( url ) ;
60
+ includeUrl . pathname += 'include' ;
61
+
62
+ const parts = [
63
+ caches . match ( revGet ( '/static/shell-start.html' ) ) ,
64
+ fetch ( includeUrl ) . catch ( ( ) => caches . match ( revGet ( '/static/offline-inc.html' ) ) ) ,
65
+ caches . match ( revGet ( '/static/shell-end.html' ) )
66
+ ] ;
67
+
68
+ const identity = new IdentityStream ( ) ;
69
+
70
+ event . waitUntil ( async function ( ) {
71
+ for ( const responsePromise of parts ) {
72
+ const response = await responsePromise ;
73
+ await response . body . pipeTo ( identity . writable , { preventClose : true } ) ;
74
+ }
75
+ identity . writable . getWriter ( ) . close ( ) ;
76
+ } ( ) ) ;
77
+
78
+ return new Response ( identity . readable , {
79
+ headers : { 'Content-Type' : 'text/html; charset=utf-8' }
80
+ } ) ;
81
+ }
82
+
83
+ addEventListener ( 'fetch' , event => {
84
+ if ( event . request . method !== 'GET' ) return ;
85
+ const url = new URL ( event . request . url ) ;
86
+
87
+ event . respondWith ( async function ( ) {
88
+ if ( url . origin === location . origin && / ^ \/ \d { 4 } \/ [ \w - ] + \/ $ / . test ( url . pathname ) ) {
89
+ return streamArticle ( event , url ) ;
90
+ }
91
+
92
+ const cachedReponse = await caches . match ( event . request ) ;
93
+ if ( cachedReponse ) return cachedReponse ;
94
+
95
+ return await fetch ( event . request ) ;
96
+ } ( ) ) ;
97
+ } ) ;
0 commit comments