Forker ce repertoire sur github.
Ensuite cloner ce repertoire :
git clone https://github.com/<your_pseudo>/meetup_pwa_29_4_2017.git
Entrer dans le repertoire avec la commande :
cd meetup_pwa_29_4_2017
Puis installer React Router:
npm install --save [email protected]
Ajouter les routes dans src/App.js
:
import React, { Component } from 'react';
import { Router, browserHistory, Route, Link } from 'react-router';
import logo from './logo.svg';
import './App.css';
const Page = ({ title }) => (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>{title}</h2>
</div>
<p className="App-intro">
This is the {title} page.
</p>
<p>
<Link to="/">Home</Link>
</p>
<p>
<Link to="/about">About</Link>
</p>
<p>
<Link to="/settings">Settings</Link>
</p>
</div>
);
const Home = (props) => (
<Page title="Home"/>
);
const About = (props) => (
<Page title="About"/>
);
const Settings = (props) => (
<Page title="Settings"/>
);
class App extends Component {
render() {
return (
<Router history={browserHistory}>
<Route path="/" component={Home}/>
<Route path="/about" component={About}/>
<Route path="/settings" component={Settings}/>
</Router>
);
}
}
export default App;
Installer les packages avec npm install
.
Maintenant, tester l'application avec npm start
.
Lighthouse est un outil gratuit de Google pour évaluer si notre application respecte les standart des progressive web apps.
Pour installer ce plugin, aller sur https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk.
Maintenant lancer un rapport Lighthouse pour évaluer l'application.
Le score est seulement de 24/100.
Le service worker est une interface entre l'appliocation et le réseau.
Pour ajouter cette interface nous devons réaliser 3 étapes :
- créer le fichier
public/service-worker.js
- enregistrer le service worker dans
public/index.html
- configurer le cache
Donc créer le fichier public/service-worker.js
Puis ajouter ce code dans public/index.html
pour enregistrer le
serviceworker :
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<title>React App</title>
</head>
<body>
<div id="root"></div>
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('service-worker.js').then(function(registration) {
// Registration was successful
console.log('ServiceWorker registration successful with scope: ', registration.scope);
}, function(err) {
// registration failed :(
console.log('ServiceWorker registration failed: ', err);
}).catch(function(err) {
console.log(err)
});
});
} else {
console.log('service worker is not supported');
}
</script>
</body>
</html>
Enfin configurer le cache dans public/service-worker.js
:
// Set this to true for production
var doCache = false;
// Name our cache
var CACHE_NAME = 'my-pwa-cache-v1';
// Delete old caches that are not our current one!
self.addEventListener("activate", event => {
const cacheWhitelist = [CACHE_NAME];
event.waitUntil(
caches.keys()
.then(keyList =>
Promise.all(keyList.map(key => {
if (!cacheWhitelist.includes(key)) {
console.log('Deleting cache: ' + key)
return caches.delete(key);
}
}))
)
);
});
// The first time the user starts up the PWA, 'install' is triggered.
self.addEventListener('install', function(event) {
if (doCache) {
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
// Get the assets manifest so we can see what our js file is named
// This is because webpack hashes it
fetch("asset-manifest.json")
.then(response => {
response.json()
})
.then(assets => {
// Open a cache and cache our files
// We want to cache the page and the main.js generated by webpack
// We could also cache any static assets like CSS or images
const urlsToCache = [
"/",
assets["main.js"]
]
cache.addAll(urlsToCache)
console.log('cached');
})
})
);
}
});
// When the webpage goes to fetch files, we intercept that request and serve up the matching files
// if we have them
self.addEventListener('fetch', function(event) {
if (doCache) {
event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
})
);
}
});
Vérifier dans la console du navigateur qu'il y a bien ce message :
Service registration successful
.
Maintenant réaliser un nouveau rapport de Lighthouse pour voir un score de 33/100.
Dans cette partie nous voulons pouvoir charger du html
avant même que react
ne les charge pour avoir du preloading.
Dans public/index.html
:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<title>React App</title>
<!-- Add in some basic styles for our HTML -->
<style type="text/css">
body {
margin: 0;
padding: 0;
font-family: sans-serif;
}
.App {
text-align: center;
}
.App-header {
background-color: #222;
height: 150px;
padding: 20px;
color: white;
}
.App-intro {
font-size: large;
}
</style>
</head>
<body>
<!-- Filler HTML as our app starts up -->
<div id="root">
<div class="App">
<div class="App-header">
<h2>Home</h2>
</div>
<p class="App-intro">
Loading site...
</p>
</div>
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('service-worker.js').then(function(registration) {
// Registration was successful
console.log('ServiceWorker registration successful with scope: ', registration.scope);
}, function(err) {
// registration failed :(
console.log('ServiceWorker registration failed: ', err);
}).catch(function(err) {
console.log(err)
});
});
} else {
console.log('service worker is not supported');
}
</script>
</body>
</html>
Vérifier le score de 46/100 sur Lighthouse.
Le manifeste sert à pouvoir accéder à l'application directement via une icone sur son smartphone.
Pour cela, il faut ajouter le fichier public/manifest.json
à la racine du répertoire
avec ce code :
{
"short_name": "My First PWA",
"name": "My First Progressive Web App",
"icons": [
{
"src":"icon.png",
"sizes": "192x192",
"type": "image/png"
}
],
"start_url": "/?utm_source=homescreen",
"background_color": "#222",
"theme_color": "#222",
"display": "standalone"
}
et ajouter l'icone public/icon.png
:
et modifier src/index.html
pour lier le manifeste :
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<!-- Add manifest -->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<!-- Tell the browser it's a PWA -->
<meta name="mobile-web-app-capable" content="yes">
<!-- Tell iOS it's a PWA -->
<meta name="apple-mobile-web-app-capable" content="yes">
<!-- Make sure theme-color is defined -->
<meta name="theme-color" content="#536878">
<title>React App</title>
</head>
Maintenant, on peut voir le score de 81/100 sur Lighthouse.
Activer le cache dans src/service-worker.js
: var doCache = true;
Puis lancer ces commandes :
npm install -g firebase-tools
firebase login
firebase init // seulement sélectionner hosting et le repertoire est 'build'
npm run build && firebase deploy
Si le score est de 100/100 vous respecter la norme PWA.
Si vous avez l'erreur insecure request found
, c'est peut-être à cause des plugins chrome qui sont éxécutés en local. Désactivez les pour atteindre les 100/100
C'est tout!