PWA

Descripción

Progressive Web Apps are user experiences that have the reach of the web, and are:

  • Confiable – Carga inmediatamente y nunca muestra el downasaur, incluso en condiciones de red inciertas.
  • Rápido – Responde rápidamente a la interacción de usuario con animaciones suaves como la seda y sin desplazamiento a tirones.
  • Cautivador – Se percibe como una app natural en el dispositivo, con una experiencia de usuario inmersiva.

This new level of quality allows Progressive Web Apps to earn a place on the user’s home screen.

Sigue leyendo más acerca de aplicaciones web progresivas (PWA) en Google.

En general, un PWA depende de las siguientes tecnologías para estar disponible:

Este plugin sirve como un lugar de encuentro para dar soporte a aquellos en WordPress que tienen la intención de que sea propuesto para un merge con el core , pieza a pieza.

☞ Please note that this feature plugin is not intended to obsolete the other plugins and themes which turn WordPress sites into PWAs. Rather, this plugin is intended to provide the PWA building blocks and coordination mechanism for these themes and plugins to not reinvent the wheel and also to not conflict with each other. For example, a theme that implements the app shell model should be able to extend the core service worker while a plugin that provides push notifications should be able to do the same. Themes and plugins no longer should have to each create a service worker on their own, something which is inherently problematic because only one service worker can be active at a time: only one service worker can win. If you are developing a plugin or theme that includes a service worker, consider relying on this PWA plugin, or at least only use the built-in implementation as a fallback for when the PWA plugin is not available.

Development of this plugin is done on GitHub. Pull requests welcome. Please see issues reported there before going to the plugin forum.

Manifest de aplicación web

Como se indica en una guía de Google:

The web app manifest is a simple JSON file that tells the browser about your web application and how it should behave when ‘installed’ on the users mobile device or desktop.

El plugin expone el manifest de la aplicación web mediante la API REST en /wp-json/app/v2/web-manifest. Una respuesta se ve así:

{
    "name": "WordPress Develop",
    "short_name": "WordPress",
    "description": "Just another WordPress site",
    "lang": "en-US",
    "dir": "ltr",
    "start_url": "https://example.com",
    "theme_color": "#ffffff",
    "background_color": "#ffffff",
    "display": "minimal-ui",
    "icons": [
        {
            "sizes": "192x192",
            "src": "https://example.com/wp-content/uploads/2018/05/example-192x192.png",
            "type": "image/png"
        },
        {
            "sizes": "512x512",
            "src": "https://example.com/wp-content/uploads/2018/05/example.png",
            "type": "image/png"
        }
    ]
}

A rel=manifest link to this endpoint is added at wp_head.

El manifest es rellenado con valores predeterminados que incluyen:

  • name: el nombre del sitio, desde get_option('blogname')
  • short_name: el título corto del sitio
  • description: el lema del sitio, desde get_option('blogdescription')
  • lang: el idioma del sitio, desde get_bloginfo( 'language' )
  • dir: la dirección del idioma del sitio, desde is_rtl()
  • start_url: la URL de la página de inicio, desde get_home_url()
  • theme_color: un fondo personalizado del tema vía get_background_color()
  • background_color: también se rellena con el fondo personalizado del tema
  • display: por defecto se usar minimal-ui.
  • icons: el icono del sitio vía get_site_icon_url()

Hay un filtro web_app_manifest que se pasa al array anterior para que los themes y plugins puedan personalizar el manifest.

Consulta los issues abiertos en GitHub y el ticket de seguimiento principal de WordPress #43328.

Service Workers

Como se menciona en Google primer:

Experiencia offline enriquecida, sincronización periódica en segundo plano, notificaciones push (características que normalmente requerirían de una aplicación nativa) están llegando a la web. Los service workers proporcionan la base tecnológica en la que se basan todas estas características.

Solo un gestor de servicios puede controlar una página en un momento determinado. Esto ha impedido que los temas y plugins de cada cual incluyan sus propios gestores de servicios debido a que solo uno actúa. Así que el primer paso para añadir soporte para los gestores de servicio en el núcleo es facilitar una API para registrar scripts, y entonces hacer que se concatenen en un script que es instalado en el gestor de servicio. Hay dos scripts que concatenados en el gestor de servicio están disponibles: uno para la portada y otro para el admin. El gestor de servicio de poraada está instalado en el ámbito de home('/') y el gestor de servicio de admin está instalado en el ámbito de admin_url('/').

La API se implementa usando la misma interfaz que WordPress para registrar scripts; de hecho WP_Service_Workers es una subclase de WP_Scripts. La instancia de esta clase es accesible vía wp_service_workers() de la misma forma que wp_scripts(). En lugar de usar wp_register_script() los scripts del service worker se registran usando wp_register_service_worker(). Esta función tiene dos argumentos:

  • $handle: El script controlador del service worker que se puede usar para señalar una dependencia de otros scripts.
  • $args: An array of additional service worker script arguments as $key => $value pairs:
    • $src: Required. The URL to the service worker on the local filesystem or a callback function which returns the script to include in the service worker.
    • $deps: Un array de service workers de los que depende un script.

Ten en cuenta que no existe un parámetro $ver (versión) debido a que los navegadores no almacenan en caché a los service workers, por lo que no es necesario.

Service worker scripts should be registered on the wp_front_service_worker and/or wp_admin_service_worker action hooks, depending on whether they should be active for the frontend service worker, the admin service worker, or both of them. The hooks are passed the WP_Service_Worker_Scripts instance, so you can optionally access its register() method directly, which wp_register_service_worker_script() is a simple wrapper of.

Aquí hay algunos ejemplos:

function register_foo_service_worker_script( $scripts ) {
    // $scripts->register() is the same as wp_register_service_worker_script().
    $scripts->register(
        'foo', // Handle.
        array(
            'src'  => plugin_dir_url( __FILE__ ) . 'foo.js', // Source.
            'deps' => array( 'app-shell' ), // Dependency.
        )
    );
}
// Register for the frontend service worker.
add_action( 'wp_front_service_worker', 'register_foo_service_worker_script' );

function register_bar_service_worker_script( $scripts ) {
    $scripts->register(
        'bar',
        array(
            // Use a script render callback instead of a source file.
            'src'  => function() {
                return 'console.info( "Hello admin!" );';
            },
            'deps' => array(), // No dependencies (can also be omitted).
        )
    );
}
// Register for the admin service worker.
add_action( 'wp_admin_service_worker', 'register_bar_service_worker_script' );

function register_baz_service_worker_script( $scripts ) {
    $scripts->register( 'baz', array( 'src' => plugin_dir_url( __FILE__ ) . 'baz.js' ) );
}
// Register for both the frontend and admin service worker.
add_action( 'wp_front_service_worker', 'register_baz_service_worker_script' );
add_action( 'wp_admin_service_worker', 'register_baz_service_worker_script' );

Consulta los issues en GitHub y el ticket de seguimiento principal en WordPress #36995.

Integrations

The plugin bundles several experimental integrations that are kept separate from the service worker core code. These integrations act as examples and proof-of-concept to achieve certain goals. While all of them are generally applicable and recommended to truly benefit from service workers, they are not crucial for the core API.

All these integrations are hidden behind a feature flag. To enable them, you can add service_worker theme support:

< ?php
add_theme_support( 'service_worker', true );

Alternatively, you can selectively enable specific integrations by providing an array when adding theme support:

 false,
        'wp-custom-logo'       => true,
        'wp-custom-background' => true,
        'wp-fonts'             => true,
    )
);

Caching

Service Workers in the feature plugin are using Workbox to power a higher-level PHP abstraction for themes and plugins to indicate the routes and the caching strategies in a declarative way. Since only one handler can be used per one route then conflicts are also detected and reported in console when using debug mode.

The API abstraction allows registering routes for caching and urls for precaching using the following two functions:
1. wp_register_service_worker_caching_route(): accepts the following two parameters:
* $route: Route regular expression, without delimiters.
* $args: An array of additional route arguments as $key => $value pairs:
* $strategy: Required. Strategy, can be WP_Service_Worker_Caching_Routes::STRATEGY_STALE_WHILE_REVALIDATE, WP_Service_Worker_Caching_Routes::STRATEGY_CACHE_FIRST, WP_Service_Worker_Caching_Routes::STRATEGY_NETWORK_FIRST, WP_Service_Worker_Caching_Routes::STRATEGY_CACHE_ONLY, WP_Service_Worker_Caching_Routes::STRATEGY_NETWORK_ONLY.
* $cache_name: Name to use for the cache.
* $plugins: Array of plugins with configuration. The key of each plugin in the array must match the plugin’s name. See https://developers.google.com/web/tools/workbox/guides/using-plugins#workbox_plugins.

  1. wp_register_service_worker_precaching_route(): accepts the following two parameters:
    • $url: URL to cache.
    • $args: An array of additional route arguments as $key => $value pairs:
    • $revision: Revision, optional.

Examples of using the API:

wp_register_service_worker_caching_route(
    '/wp-content/.*\.(?:png|gif|jpg|jpeg|svg|webp)(\?.*)?$',
        array(
            'strategy'  => WP_Service_Worker_Caching_Routes::STRATEGY_CACHE_FIRST,
            'cacheName' => 'images',
            'plugins'   => array(
                'expiration'        => array(
                    'maxEntries'    => 60,
                    'maxAgeSeconds' => 60 * 60 * 24,
            ),
        ),
    )
);
wp_register_service_worker_precaching_route(
    'https://example.com/wp-content/themes/my-theme/my-theme-image.png',
    array(
        'revision' => get_bloginfo( 'version' ),
    )
);

If you would like to opt-in to a caching strategy for navigation requests, you can do:

add_filter( 'wp_service_worker_navigation_caching_strategy', function() {
    return WP_Service_Worker_Caching_Routes::STRATEGY_STALE_WHILE_REVALIDATE;
} );

add_filter( 'wp_service_worker_navigation_caching_strategy_args', function( $args ) {
    $args['cacheName'] = 'pages';
    $args['plugins']['expiration']['maxEntries'] = 50;
    return $args;
} );

👉 If you previously added a wp_service_worker_navigation_preload filter to disable navigation preload,
you should probably remove it. This was originally needed to work around an issue with ensuring the offline
page would work when using a navigation caching strategy, but it is no longer needed and it should be removed
improved performance. Disabling navigation
preload is only relevant when you are developing an app shell.

Offline / 500 error handling

The feature plugins offers improved offline experience by displaying a custom template when user is offline instead of the default message in browser. Same goes for 500 errors — a template is displayed together with error details.

Themes can override the default template by using error.php, offline.php, and 500.php in you theme folder. error.php is a general template for both offline and 500 error pages and it is overridden by offline.php and 500.php if they exist.

Note that the templates should use wp_service_worker_error_message_placeholder() for displaying the offline / error messages. Additionally, on the 500 error template the details of the error can be displayed using the function wp_service_worker_error_details_template( $output ).

For development purposes the offline and 500 error templates are visible on the following URLs on your site:
https://your-site-name.com/?wp_error_template=offline;
https://your-site-name.com/?wp_error_template=500

Default value for $output is the following:
‘ . esc_html__( ‘More Details’, ‘pwa’ ) . ‘{{{error_details_iframe}}} where {{{error_details_iframe}}} will be replaced by the iframe.

In case of using the <iframe> within the template {{{iframe_src}}} and {{{iframe_srcdoc}}} are available as well.

For example this could be done:

wp_service_worker_error_details_template(
    '' . esc_html__( 'More Details', 'pwa' ) . ''
);

Offline Commenting

Another feature improving the offline experience is Offline Commenting implemented leveraging Workbox Background Sync API.

In case of submitting a comment and being offline (failing to fetch) the request is added to a queue and once the browsers «thinks» the connectivity is back then Sync is triggered and all the commenting requests in the queue are replayed. This meas that the comment will be resubmitted once the connection is back.

Available actions and filters

Here is a list of all available actions and filters added by the feature plugin.

Filters:
wp_service_worker_skip_waiting: Filters whether the service worker should update automatically when a new version is available.
– Has one boolean argument which defaults to true.
wp_service_worker_clients_claim: Filters whether the service worker should use clientsClaim() after skipWaiting().
– Has one boolean argument which defaults to false;
wp_service_worker_navigation_preload: Filters whether navigation preload is enabled. Has two arguments:
– boolean which defaults to true;
$current_scope, either 1 (WP_Service_Workers::SCOPE_FRONT) or 2 (WP_Service_Workers::SCOPE_ADMIN);
wp_offline_error_precache_entry: Filters what is precached to serve as the offline error response on the frontend.
– Has one parameter $entry which is an array:
$url URL to page that shows the offline error template.
$revision Revision for the template. This defaults to the template and stylesheet names, with their respective theme versions.
wp_server_error_precache_entry: Filters what is precached to serve as the internal server error response on the frontend.
– Has one parameter $entry which is an array:
$url URL to page that shows the server error template.
$revision Revision for the template. This defaults to the template and stylesheet names, with their respective theme versions.
wp_service_worker_error_messages: Filters the offline error messages displayed on the offline template by default and in case of offline commenting.
– Has one argument with array of messages:
$default The message to display on the default offline template;
$comment The message to display on the offline template in case of commenting;
wp_streaming_header_precache_entry: Filters what is precached to serve as the streaming header.
– Has one $entry param which is an array with the following arguments:
$url URL to streaming header fragment.
$revision Revision for the entry. Care must be taken to keep this updated based on the content that is output before the stream boundary.

Actions:
wp_front_service_worker: Fires before serving the frontend service worker, when its scripts should be registered, caching routes established, and assets precached.
– Has one argument $scripts WP_Service_Worker_Scripts Instance to register service worker behavior with.
wp_admin_service_worker: Fires before serving the wp-admin service worker, when its scripts should be registered, caching routes established, and assets precached.
– Has one argument $scripts WP_Service_Worker_Scripts Instance to register service worker behavior with.
wp_default_service_workers: Fires when the WP_Service_Worker_Scripts instance is initialized.
– Has one argument $scripts WP_Service_Worker_Scripts Instance to register service worker behavior with.

HTTPS

HTTPS es un requisito previo para las aplicaciones web progresivas. Un service worker solo puede instalarse en sitios servidos mediante HTTPS. Por esta razón, se debe mejorar aún más el soporte del núcleo para HTTPS, continuando el gran progreso realizado en los últimos años.

Por ahora, el plugin proporciona una API para detectar si un sitio soporta HTTPS. A partir de ahí, la intención es que esto pueda ser usado para dotar a un usuario de una opción para cambiar a HTTPS, que también deberá incluir soporte para reescribir URLs de HTTP a HTTPS. Consulta los issues en GitHub y el ticket de seguimiento principal en WordPress #28521.

You can optionally add an HSTS header (HTTP Strict-Transport-Security). This indicates to the browser to only load the site with HTTPS, not HTTP.

/**
 * Adds an HSTS header to the response.
 *
 * @param array $headers The headers to filter.
 * @return array $headers The filtered headers.
 */
add_filter( 'wp_headers', function( $headers ) {
    $headers['Strict-Transport-Security'] = 'max-age=3600'; // Or another max-age.
    return $headers;
} );

This can prevent a case where users initially visit the HTTP version of the site, and are redirected to a malicious site before a redirect to the proper HTTPS version.

The wp_headers filter allows you to add a Strict-Transport-Security header for this.

Please see the documentation for the directives, including the max-age.

Reseñas

junio 15, 2019
No noticeable performance improvement after activation. In fact, it slows down our website in many cases. See this plugin's Support Threads for more information.
diciembre 19, 2018
Currently this is a pain to manage. Great effort and hopefully will be merged sooner rather than later!
diciembre 12, 2018
tienes que hacer el manifiesto y tienes que hacer el service worker entonces cual es el chiste!!! muy mal plugin
Leer todas las 6 reseñas

Colaboradores y desarrolladores

“PWA” es un software de código abierto. Las siguientes personas han colaborado con este plugin.

Colaboradores

“PWA” ha sido traducido a 3 idiomas locales. Gracias a los traductores por sus contribuciones.

Traduce “PWA” a tu idioma.

¿Interesado en el desarrollo?

Revisa el código , echa un vistazo al repositorio SVN o suscríbete al registro de desarrollo por RSS.

Registro de cambios

For the plugin’s changelog, please see the Releases page on GitHub.