J'utilise create-react-app avec un serveur express .
create-react-app
a un ServiceWorker préconfiguré qui met en cache les actifs locaux ( https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#making-a- progressive-web-app ).
Le problème que j'ai rencontré lorsque j'ai essayé de publier sur mon serveur est que le fichier service-worker.js
était disponible, mais que des erreurs se produisaient dans la console de mon navigateur lorsqu'il a essayé de l'enregistrer.
Sur Firefox, j'ai eu cette erreur:
Erreur lors de l'enregistrement du technicien:
TypeError: Le script ServiceWorker à https://my-domain.com/service-worker.js pour la portée https://my-domain.com/ a rencontré une erreur lors de l'installation.
Sur Chrome, j'obtiens l'erreur la plus descriptive:
Erreur lors de l'enregistrement du service worker: DOMException: impossible d'enregistrer un ServiceWorker: le script a un type MIME non pris en charge ('text/html').
En effet, si je cherche dans l’onglet Réseau de mes outils de développement et que je cherche le fichier service-worker.js
, je constate qu’il contient un type MIME incorrect dans les en-têtes HTTP.
Je ne pouvais pas comprendre, cependant, pourquoi il a le mauvais type MIME?
Dans mon application serveur Express, j'ai un itinéraire générique (astérisque/*) qui redirige vers index.html
:
// Load React App
// Serve HTML file for production
if (env.name === "production") {
app.get("*", function response(req, res) {
res.sendFile(path.join(__dirname, "public", "index.html"));
});
}
Ceci est un modèle de conception très commun. Cependant, cela signifie que toutes les demandes de fichiers texte inconnus sont initialement redirigées vers index.html
et sont donc renvoyées avec le type MIME de "text/html"
, même s'il s'agit en fait d'un fichier JavaScript ou SVG ou d'un autre type de fichier en texte clair.
La solution que j'ai trouvée consistait à ajouter une route spécifique pour service-worker.js
avant la route générique:
app.get("/service-worker.js", (req, res) => {
res.sendFile(path.resolve(__dirname, "public", "service-worker.js"));
});
app.get("*", function response(req, res) {
res.sendFile(path.join(__dirname, "public", "index.html"));
});
Désormais, lorsque le navigateur recherche service-worker.js
, Express le renvoie avec le type MIME approprié.
(Notez que si vous essayez d'ajouter la route service-worker.js
après le caractère générique, cela ne fonctionnera pas car la route générique sera remplacée.)
Assurez-vous que le fichier du technicien de maintenance est généré (Chrome DevTools -> Sources -> Système de fichiers). Vous pouvez recevoir une telle erreur si le fichier de l’agent de service n’est pas généré (vérifiez votre script de déploiement).
Les types MIME pris en charge par ServiceWorker sont 'text/javascript', application/javascript et application/x-javascript. arrivé à votre fichier de serveur et définir
response.writeHead(201, {
'Content-Type': 'application/javascript'
});
Remplacement
'/service-worker.js'
avec
'./service-worker.js'
(dans navigator.serviceWorker.register('/service-worker.js')
)
résolu mon problème similaire.
Réagir: public/index.html
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('sw-cached-site.js', function() {
navigator.serviceWorker.register('service-worker.js', {
scope: '/',
});
});
}
window.process = { env: { NODE_ENV: 'production' } };
</script>
Remarque: app/site complet Public/sw-cached-site.js
const cacheName = 'v1';
self.addEventListener('activate', (e) =>{
e.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cache => {
if(cache !== cacheName) {
return caches.delete(cache);
}
})
)
})
)
});
self.addEventListener('fetch', e => {
e.respondWith(
fetch(e.request)
.then(res => {
const resClone = res.clone();
caches
.open(cacheName)
.then(cache => {
cache.put(e.request, resClone);
});
return res;
}).catch(err => caches.match(e.request).then(res => res))
);
});