Yes. To cache many files from multiple directories ...
I use a helper function in the service worker
that I named "getFileArray( ... )."
It takes one string argument of the directory name.
For multiple directories, I use an array of these in
Promise.all:
let cache_name = "cache-A";
let filesToCache = [
"https://myApp.com/",
"index.php?launcher=true;homescreen=1",
"manifest.json",
"favicon.ico",
];
self.addEventListener( "install", eo => {
self.skipWaiting();
eo.waitUntil( filesAreCached() );
} );
///////| helper functions |/////////
function filesAreCached(){
Promise.all([
/* name the directories whose files you wish to cache */
getFileArray( "js" ),
getFileArray( "css" ),
getFileArray( "images" ),
getFileArray( "screens" ),
getFileArray( "modals" )
])
.then( promiseArray => {
let promisedFiles = [];
promiseArray.forEach( array => {
promisedFiles = promisedFiles.concat( array ) ;
} );
return promisedFiles;
})
.then( promisedFiles => {
filesToCache = filesToCache.concat( promisedFiles );
console.log( "Cached files:", filesToCache );
return self.caches.open( cache_name );
})
.then( cache => cache.addAll( filesToCache ) );
}
/*
the following function calls a server script that returns an array of filenames,
each one prepended with the directory name:
*/
async function getFileArray( directory ){
let form = new FormData();
form.append( `directory`, directory );
let fileArray = await fetch( `php/getFileArray.php`, { method: `POST`, body: form })
.then( response => response.json() ) ;
return fileArray;
}
The PHP code (getFileArray.php) looks like this:
<?php
/*
Motivation: To help provide an accurate list of files
for JavScript service workers to cache. Saves time,
tedium, and possible typos in doing it manually.
Use the POSTed directory path to return an array
that lists all the files in that directory,
less the "." and ".." entries.
Prepend the directory name to the filenames so that
we have the "full path" to each file.
Return this array as a json string.
*/
$directory = $_POST["directory"] ;
/*
You should probably sanitize $directory of all "../" prefixes
in order to prevent a Directory Traversal Attack.
Using str_replace("/", "", $directory) has been suggested.
It throws an error but prevents the attack.
*/
$filelistArray = scandir( "../" . $directory );
$cleanFileArray = array();
foreach( $filelistArray as $file ){
if ( $file !== "." and $file !== ".." ){
array_push( $cleanFileArray, $directory . "/" . $file );
}
}
$fileArrayJson = json_encode( $cleanFileArray );
exit( $fileArrayJson );
?>
Of course, any backend language can be used.
This technique might be a little unsophisticated,
but it works for me :)