Une Progressive Web App est une application web perfectible qui repose sur le principe de l’amélioration progressive afin de s’adapter à tous les utilisateurs, quels que soient le système d'exploitation et le navigateur Web utilisés.
Source: https://fr.semrush.com/blog/progressive-web-app/C’est grâce aux Service Workers, au fichier Manifest et à une conception App Shell que la Progressive Web App va pouvoir proposer une expérience similaire aux applications mobiles.
const SEP = 'XXYXXX';
function inArray(needle, haystack) {
var type = typeof haystack;
if(( type == 'number' ) || ( type == 'string' )) {
if(needle == haystack) {
return true;
}
return false;
}
var i = haystack.length - 1;
while(i >= 0){
if(needle == haystack[i]){
return true;
}
i--;
}
return false;
}
/**********************************/
/** CETTE FONCTON REND JSON/TEXT **/
/** SUIVANT LE CONTENT-TYPE **/
/** DE LA REPONSE. **/
/**********************************/
const textJson = function(response) {
return new Promise(function(resolve, reject) {
if(response) {
var Resp = response.clone();
if(Resp.ok) {
if (Resp.headers.get("content-type").match('application/json')) {
Resp.json().then(function(json) {
resolve(JSON.stringify(json));
}, function(error) {
reject('1 Error while fetching file : ' + error.message);
})
} else {
Resp.text().then(function(text) {
resolve(text);
}, function(error) {
reject('2 Error while fetching file : ' + error.message);
})
}
} else {
reject('Error with response Status : ' + Resp.status + ' : ' + Resp.statusText);
}
} else {
reject('Response undefined');
}
});
};
// Small library to improve on fetch() usage
const api = function(method, url, data, headers = {}){
return fetch(url, {
method: method.toUpperCase(),
body: data, // send it as stringified json
credentials: api.credentials, // to keep the session on the request
headers: Object.assign({}, api.headers, headers) // extend the headers
}).then(res => res.ok ? Promise.resolve(res) : Promise.reject(res));
};
// Defaults that can be globally overwritten
api.credentials = 'include';
api.headers = {
// 'csrf-token': window.csrf || '', // only if globally set, otherwise ignored
'mode': 'cors'
// 'Accept': 'text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8', // receive text/html
// 'Content-Type': 'text/html; charset=utf-8' // send text/html
};
// Convenient methods
['get', 'post', 'put', 'delete', 'head'].forEach(method => {
api[method] = api.bind(null, method);
});
/*****************************************/
/** ON CHARGE LES HEADERS MIS EN CACHE. **/
/*****************************************/
function getStoredHeaders(request, cache) {
var Request = request.clone();
var url = new URL(Request.url, location.href);
var file = 'Headers_' + url.pathname;
cache.match(file).then(function(response) {
if (response) {
Response = response.clone();
console.log('Response cache = ' + Response);
textJson(Response).then(function(text) {
console.log('Succeded while fetching file headers : ' + file + ' with : ' + text);
var index = text.indexOf(SEP);
if(index !== -1) {
var lastModified = text.substring(0, index)
var etags = text.substring(index + strlen(SEP)));
return new Array(lastModified, etags);
}
return null;
}, function(error) {
reject('headers not in cache : ' + file + ' , with error : ' + error.message);
return null;
})
} else {
reject('headers not in cache : ' + file);
return null;
}
}, function(error) {
reject('headers not in cache : ' + file + ' , with error : ' + error.message);
return null;
})
return null;
}
/*****************************************/
/** ON MET EN CACHE LES HEADERS. **/
/*****************************************/
function storedHeaders(request, cache, lastModified, etags) {
var Request = request.clone();
var url = new URL(Request.url, location.href);
var file = 'Headers_' + url.pathname;
var tmp_value = lastModified + SEP + etags;
/*************************/
/** ON MET EN CACHE **/
/** LE FICHIER **/
/*************************/
cache.put(file, tmp_value).then(function(result) {
console.log('file : ' + file + ' set to the cache.');
return true;
}, function(error) {
console.log('file : ' + file + ' not set in the cache, with error : ' + error.message);
})
return false;
}
function isNotModified(request, cache)
{
var Request = request.clone();
var Request1 = request.clone();
var Request2 = request.clone();
var Request3 = request.clone();
/*************************/
/** D'APRES LES HEADERS **/
/*************************/
var lastModified = Request1.headers.get('Last-Modified');
var etags = Request2.headers.get('ETag');
/*************************/
/** D'APRES LES ENREG **/
/*************************/
var result = new Array();
result = getStoredHeaders(Request, cache);
if(result === null) {
return false;
}
var LastModified = result[0];
var Etag = result[1];
var notModified = false;
if (etags) {
notModified = (inArray(Etag, etags) || inArray('*', etags)) && (!lastModified || LastModified == lastModified);
} elseif (lastModified) {
notModified = lastModified == LastModified;
}
if (notModified) {
/*********************/
/** FROM THE CACHE **/
/*********************/
this->setNotModified();
} else {
/*********************/
/** NOT THE CACHE **/
/*********************/
storedHeaders(Request3, cache, lastModified, etags);
}
return notModified;
}