Uso del complemento VitePWA para sitios fuera de línea trucos CSS
Complemento VitePWA desde antonio fu Gran herramienta para su sitio web Vite. Le ayuda a agregar un trabajador de servicio para manejar:
- Soporte fuera de línea
- Activos en efectivo y contenido
- Avisar al usuario cuando haya nuevo contenido disponible
- ... y otros extras!
Juntos entenderemos el concepto de trabajador de servicio y luego crearemos uno directamente con la ayuda del complemento VitePWA.
¿Nuevo en Werther? Ver mi anterior publicación de introducción.
contenido
-
personal de servicio, introducción
-
Control de versiones y manifiestos
-
Nuestro primer servicio
-
¿Qué hay de la funcionalidad fuera de línea?
-
Cómo se actualizan los trabajadores de servicio
-
Una mejor manera de actualizar el contenido
-
caché en tiempo de ejecución
-
Agregue su propio contenido a Service Worker
-
me tuerzo
personal de servicio, introducción
Antes de ingresar al complemento VitePWA, hablemos brevemente trabajador del servicio yo mismo.
una personal es un proceso en segundo plano que se ejecuta en un subproceso separado en su aplicación web. Los trabajadores de servicio tienen la capacidad de interceptar solicitudes de red y hacer... cualquier cosa. Las posibilidades son sorprendentemente amplias. Por ejemplo, puede interceptar solicitudes de archivos TypeScript y compilarlos sobre la marcha. O puede interceptar solicitudes de archivos de video y realizar una transcodificación avanzada, que actualmente no es compatible con los navegadores. Más a menudo, los trabajadores del servicio se utilizan para almacenar en caché los activos, tanto para mejorar el rendimiento del sitio como para permitir que funcione. algo cuando estás desconectado.
Cuando alguien llega a su sitio web por primera vez, el técnico de servicio creado por el complemento VitePWA lo hará. API de almacenamiento en cachéEl resultado es que la próxima vez que visite su sitio, el navegador cargará estos recursos desde el caché sin realizar una solicitud de red. La primera vez que visite su sitio, porque el personal solo Todo está prealmacenado en caché, y es posible que la siguiente ubicación en la que un usuario haga clic ya esté prealmacenada, lo que permite que el navegador omita por completo las solicitudes de red.
Control de versiones y manifiestos
Es posible que se pregunte qué sucede con los trabajadores de servicios cuando se actualiza su código. Si su técnico de servicio almacena en caché, diga foo.js
y cambia este archivo, desea que el trabajador del servicio descargue la versión actualizada la próxima vez que el usuario visite el sitio.
pero realmente no lo haces foo.js
documento. Por lo general, el sistema de construcción crea algo similar foo-ABC123.js
donde "ABC123" es el hash del archivo. Si actualiza foo.js
, se puede enviar la próxima implementación de su sitio foo-XYZ987.js
¿Cómo maneja esto el asistente?
Resulta que la API Service Worker es una excepcional Primitivas de bajo nivel. Si está buscando una solución llave en mano natural entre ella y la API de almacenamiento en caché, se sentirá decepcionado. En principio, la creación de trabajadores de servicios debería estar parcialmente automatizada y vinculada al sistema constructivo. Debe ver todos los activos creados por su compilación, codificar estos nombres de archivo en el trabajador del servicio, tener un código de almacenamiento en caché previo y, lo que es más importante, no te pierdas archivos en caché.
Si se actualiza el código, el archivo del trabajador del servicio también cambia que contiene nuevo Nombre de archivo de valor hash. La próxima vez que el usuario inicie sesión en la aplicación, el nuevo service worker deberá instalar un nuevo archivo de manifiesto, comparar el nuevo archivo de manifiesto con el que se encuentra actualmente en la memoria caché, mostrar los archivos emergentes que ya no se necesitan y almacenar en caché el nuevo archivo. contenido de la misma manera.
Este es un trabajo ridículo y difícil de solucionar. Si bien puede ser un proyecto interesante, en la práctica querrá utilizar un producto probado para desarrollar a su personal de servicio, y los mejores productos son caja de trabajo, este es alguien de google.
Incluso Workbox es un poco primitivo de bajo nivel. Necesita detalles sobre sus archivos almacenados previamente en caché que están ocultos en sus herramientas de compilación. Es por eso que usamos el complemento VitePWA. Él usa Workbox entre bastidores y configura los paquetes creados por Vite con toda la información necesaria. paquete web y enroscado Si prefiere usar estos paquetes, use complementos.
Nuestro primer servicio
Supongo que ya tienes una web basada en Vite, si no, no lo dudes. Crear De todo tipo Plantillas disponibles.
Primero, instale el complemento VitePWA:
npm i vite-plugin-pwa
Importaremos el complemento en la configuración de Vite:
import { VitePWA } from "vite-plugin-pwa"
Luego lo usamos en la configuración:
enchufar: [
VitePWA()
We’ll add more options in a bit, but that’s all we need to create a surprisingly useful service worker. Now let’s register it somewhere in the entry of our application with this code:
import { registerSW } from "virtual:pwa-register";
if ("serviceWorker" in navigator) {
// && !/localhost/.test(window.location)) {
registerSW();
}
Don’t let the code that’s commented out throw you for a loop. It’s extremely important, in fact, as it prevents the service worker from running in development. We only want to install the service worker anywhere that’s not on the localhost where we’re developing, that is, unless we’re developing the service worker itself, in which case we can comment out that check (and revert before pushing code to the main branch).
Let’s go ahead and open a fresh browser, launch DevTools, navigate to the Network tab, and run the web app. Everything should load as you’d normally expect. The difference is that you should see a whole slew of network requests in DevTools.
That’s Workbox pre-caching the bundles. Things are working!
What about offline functionality?
So, our service worker is pre-caching all of our bundled assets. That means it will serve those assets from cache without even needing to hit the network. Does that mean our service worker could serve assets even when the user has no network access? Indeed, it does!
And, believe it or not, it’s already done. Give it a try by opening the Network tab in DevTools and telling Chrome to simulate offline mode, like this.
Let’s refresh the page. You should see everything load. Of course, if you’re running any network requests, you’ll see them hang forever since you’re offline. Even here, though, there are things you can do. Modern browsers ship with their own internal, persistent database called IndexedDB. There’s nothing stopping you from writing your own code to sync some data to there, then write some custom service worker code to intercept network requests, determine if the user is offline, and then serve equivalent content from IndexedDB if it’s in there.
But a much simpler option is to detect if the user is offline, show a message about being offline, and then bypass the data requests. This is a topic unto itself, which I’ve written about in much greater detail.
Before showing you how to write, and integrate your own service worker content, let’s take a closer look at our existing service worker. In particular, let’s see how it manages updating/changing content. This is surprisingly tricky and easy to mess up, even with the VitePWA plugin.
Before moving on, make sure you tell Chrome DevTools to put you back online.
How service workers update
Take a closer look at what happens to our site when we change the content. We’ll go ahead and remove our existing service worker, which we can do in the Application tab of DevTools, under Storage.
Click the “Clear site data” button to get a clean slate. While I’m at it, I’m going to remove most of the routes of my own site so there’s fewer resources, then let Vite rebuild the app.
Look in the generated sw.js
to see the generated Workbox service worker. There should be a pre-cache manifest inside of it. Mine looks like this:
If sw.js
is minified, run it through Prettier to make it easier to read.
Now let’s run the site and see what’s in our cache:
Let’s focus on the settings.js file
. Vite generated assets/settings.ccb080c2.js
based on the hash of its contents. Workbox, being independent of Vite, generated its own hash of the same file. If that same file name were to be generated with different content, then a new service worker would be re-generated, with a different pre-cache manifest (same file, but different revision) and Workbox would know to cache the new version, and remove the old when it’s no longer needed.
Again, the filenames will always be different since we’re using a bundler that injects hash codes into our file names, but Workbox supports dev environments which don’t do that.
Since the time writing, the VitePWA plugin has been updated and no longer injects these revision hashes. If you’re attempting to follow along with the steps in this article, this specific step might be slightly different from your actual experience. See this GitHub issue for more context.
If we update our settings.js
file, then Vite will create a new file in our build, with a new hash code, which Workbox will treat as a new file. Let’s see this in action. After changing the file and re-running the Vite build, our pre-cache manifest looks like this:
Now, when we refresh the page, the prior service worker is still running and loading the prior file. Then, the new service worker, with the new pre-cache manifest is downloaded and pre-cached.
Note the corollary here: our old content is still being served to the user since the old service worker is still running. The user is unable to see the change we just made, even if they refresh because the service worker, by default, guarantees any and all tabs with this web app are running the same version. If you want the browser to show the updated version, close your tab (and any other tabs with the site), and re-open it.
Workbox did all the legwork of making this all come out right! We did very little to get this going.
A better way to update content
It’s unlikely that you can get away with serving stale content to your users until they happen to close all their browser tabs. Fortunately, the VitePWA plugin offers a better way. The registerSW
function accepts an object with an onNeedRefresh
method. This method is called whenever there’s a new service worker waiting to take over. registerSW
also returns a function that you can call to reload the page, activating the new service worker in the process.
That’s a lot, so let’s see some code:
if ("serviceWorker" in navigator) {
// && !/localhost/.test(window.location) && !/lvh.me/.test(window.location)) {
const updateSW = registerSW({
onNeedRefresh() {
Toastify({
text: `<h4 style="display: inline">An update is available!</h4>
<br><br>
<a class="do-sw-update">Click to update and reload</a> `,
escapeMarkup: false,
gravity: "bottom",
onClick() {
updateSW(true);
}
}).showToast();
}
});
}
I’m using the toastify-js library to show a toast UI component to let users know when a new version of the service worker is available and waiting. If the user clicks the toast, I call the function VitePWA gives me to reload the page, with the new service worker running.
One thing to remember here is that, after you deploy the code to show the toast, the toast component won’t show up the next time you load your site. That’s because the old service worker (the one before we added the toast component) is still running. That requires manually closing all tabs and re-opening the web app for the new service worker to take over. Then, the next time you update some code, the service worker should show the toast, prompting you to update.
Why doesn’t the service worker update when the page is refreshed? I mentioned earlier that refreshing the page does not update or activate the waiting service worker, so why does this work? Calling this method doesn’t only refresh the page, but it calls some low-level Service Worker APIs (in particular skipWaiting
) as well, giving us the outcome we want.
Runtime caching
We’ve seen the bundle pre-caching we get for free with VitePWA for our build assets. What about caching any other content we might request at runtime? Workbox supports this via its runtimeCaching
feature.
Here’s how. The VitePWA plugin can take an object, one property of which is workbox
, which takes Workbox properties.
const getCache = ({ name, pattern }: any) => ({
urlPattern: pattern,
handler: "CacheFirst" as const,
options: {
cacheName: name,
expiration: {
maxEntries: 500,
maxAgeSeconds: 60 * 60 * 24 * 365 * 2 // 2 years
},
cacheableResponse: {
statuses: [200]
}}}); // ... enchufar: [
VitePWA({
workbox: {
runtimeCaching: [
getCache({
pattern: /^https://s3.amazonaws.com/my-library-cover-uploads/,
name: "local-images1"
}),
getCache({
pattern: /^https://my-library-cover-uploads.s3.amazonaws.com/,
name: "local-images2"
})
]
}})]// ...
Lo sé, es mucho código. Pero todo lo que realmente hace es decirle a Workbox que almacene en caché todo lo que ve que coincida con esas plantillas de URL. Documentación Proporcione más información si desea entrar en más detalles.
Ahora que la actualización está en vigor, podemos ver que nuestro técnico de servicio está dando servicio a estos recursos.
Podemos ver el caché correspondiente creado.
Agregue su propio contenido a Service Worker
Suponga que desea avanzar con el personal de servicio. Desea agregar un código para sincronizar datos con IndexedDB, agregar un controlador de recuperación y responder con datos de IndexedDB cuando el usuario está desconectado (nuevamente, mi publicación anterior cubrió las complejidades de IndexedDB). Pero, ¿cómo ponemos nuestro propio código en el service worker que Vite crea para nosotros?
Podemos usar otra opción de Workbox para esto: importScripts
.
VitePWA({
workbox: {
importScripts: ["sw-code.js"],
Aquí el trabajador de servicio le preguntará sw-code.js
durante la ejecución. En este caso, asegúrese de tener sw-code.js
Un archivo que puede ser proporcionado por su aplicación. La forma más fácil de lograr esto es pegarlo public
carpeta (ver documentación rápida Descripción detallada).
Si este archivo comienza a crecer hasta un tamaño que debe desglosarse mediante la importación de JavaScript, asegúrese de fusionarlo para evitar que el trabajador del servicio intente ejecutar la declaración de importación (que puede ejecutarse o no). Puede crear una versión separada de Vite.
me tuerzo
A finales de 2021, CSS-Tricks le preguntó a un grupo de front-end qué podían hacer para mejorar su sitio web. Chris Ferdinandi recomienda el uso de personal de apoyo. Bueno, eso es exactamente lo que hicimos en este artículo, y es relativamente simple, ¿no es así? Sugerencia de sombrero gracias a VitePWA y Workbox and Cache API.
Los empleados que utilizan la API de caché pueden mejorar significativamente el rendimiento de su aplicación web. Si bien puede parecer un poco aterrador o confuso al principio, es bueno saber que tenemos herramientas como el complemento VitePWA que simplifican mucho las cosas. Instale el complemento y deje que haga el trabajo duro. Por supuesto, los trabajadores de servicio pueden hacer cosas más avanzadas y VitePWA se puede usar para funciones más sofisticadas, ¡pero los sitios fuera de línea son un excelente lugar para comenzar!
Deja una respuesta