PWA => détail ou contenu complet ?

WRInaute accro
Bonjour

C'est pour une PWA.

Quelle est la façon la plus optimisée de programmer une PWA ?

1) Dans le détail : Identifier les pavés de la page et les remplir,

2) Pour la page entière, convertir le JSON en HTML en une seule fois ?

Merci beaucoup pour votre aide.
 
WRInaute accro
Faire un site/app en HTML/CSS/JS classique.
Mettre en cache les ressources via le Service Worker. Pour rendre le site/app utilisable ou partiellement utilisable en hors ligne.

Convertir le JSON en HTML ? o_O 100% USELESS.

Revois les bases:
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.

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.
Source: https://fr.semrush.com/blog/progressive-web-app/
 
WRInaute accro
Bonjour

Dans l'optique de faire une PWA.

A supposer que je fasse des affichages de page par portions/pavés, quelle serait la meilleure structure de data source => cible pour représenter le format d'une page ?

Une page ayant 2 dimensions, comment formater la source décrivant le format d'une page ?

Ou bien, sans se casser la tête, programmer la page statique et la remplir avec du contenu dynamique, sans vouloir trop automatiser le processus ?

Dans ce cas, j'aurais à me coltiner chaque page à la main. Dur, dur...

Ou bien aussi, mettre des tokens dans le contenu statique pour automatiser le remplissage ?

Merci beaucoup de votre aide.
 
WRInaute accro
Voilà voilà.

Mieux vaut tard que jamais.

Associer à chaque "id" de page, l'url de contenu de son pavé.

J'ai fait le format de index.php de mon site.

5 pavés.

Comment profiter des avantages de HTTP/2 en chargeant les différentes urls en même temps ?

Merci.
 
WRInaute accro
Un petit détail.

Comment signaler ( pour le cache ), qu'une url a été modifiée ?

Est-il possible de mettre le filemtime() ou équivalent, dans le header HTTP ?

Sinon, quels délais prenez-vous, avant effacement du cache des fichiers ?

Merci beaucoup.

Pour ce qui est des associations "id" => url, comment procédez-vous ?

Mettez-vous l'url en commentaire dans le source ?

Merci beaucoup de votre aide.

Amicalement.
 
WRInaute accro
Rebond.

Je met le header : "Last-Modified" dans le header, et je le lis en Javasript.

JavaScript:
  var LastModified = response.headers.get("last-modified");

Mais quel délai ?

Newbie en PWA...
 
WRInaute accro
Last but not least...

Quel algorithme de cache basé sur le timestamp ?

1) Timestamp constant en cache, si trop ancien refaire cache et timestamp,

2) Autres.

Merci beaucoup.
 
WRInaute accro
Pardon

Si je tenais compte à la fois de l'"ETag" ( hashcode ) et du "Last-Modified" ( timestamp ), quel serait l'algorithme idéal pour des lectures cache/directes ?

Si l'Etag lu dans le header séparément ne correspondait pas à celui dans le cache, on refait le cache, sinon non.

Y a-t-il besoin du "Last-Modified" ( timestamp ) dans cette occurrence ?

Merci.
 
WRInaute accro
Rebond

J'ai commis cette petite api de cache, en fonction des headers : ETag et LastModified.

Pas encore testé, merci de me dire s'il y a des fautes.



Code:
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;
}
 
Dernière édition:
WRInaute accro
Bon

J'ai un problème pour le ETag.

Il devrait ne dépendre que du contenu html interprété.

Ou bien, ce serait un identificateur précisément de ce contenu html.

J'ai le choix entre le produire en PHP, ou laisser le serveur web le faire.

La deuxième solution est viable ou non ?

Merci beaucoup.
 
WRInaute accro
Voilà c'est fait.

Super utile la classe de cache de noren.

Maintenant il y a :

etag: hash('sha256', $html)

et :

last_modified: UTC_Date lors de la mise à jour du cache.

Testez si voulez : https://www.pronostics-courses.fr

Cà marche sur toutes les pages, seul le code de class_cache.inc.php est changé.

Je ne sais pas comment Last-Modified pourrait contenir la date plutôt que le timestamp.

Enjoy.
 
Discussions similaires
Haut