PWA

Descrição

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

  • Confiável – Carregue instataneamente e nunca mostre o “downasaur”, mesmo em conexões instáveis.
  • Rápida – Responda as interações do usuário rapidamente, com animações suaves sem rolagem abrupta.
  • Cativante – Sinta-se como uma aplicação nativa,
    com uma experiência imersiva.

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

Continue lendo mais sobre Progressive Web Apps (PWA) do Google.

Em geral, uma PWA depende das seguintes tecnologias para estar disponível:

Este plug-in serve como um local para implementar suporte a eles no WordPress com a intenção de ser proposto para mesclagem principal, peça por peça.

☞ 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.

O desenvolvimento deste plugin é feito no GitHub. Pull requests serão bem vindos. Por favor veja as problemas reportados aqui antes de criar uma requisição no forum do plugin.

Web App Manifest

Como visto em Guia do Google:

O web app manifest é um simples arquivo JSON que informa o navegador sobre seu aplicativo web e como deve se comportar quando ‘instalado’ no dispositivo móvel ou na área do trabalho do usuário.

O plugin expõe o web app manifest por meio da API REST em /wp-json/wp/v2/web-app-manifest. Uma resposta é semelhante a:

{
    "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"
        }
    ]
}

Um rel=manifest conectado com este endpoint é adicionado em wp_head.

O manifesto é preenchido com valores padrões incluído:

  • name: o título do site por get_option('blogname')
  • short_name: Título de site truncado
  • description: o slogan do site em get_option('blogdescription')
  • lang: o idioma do site em get_bloginfo( 'language' )
  • dir: a direção do idioma do site de is_rtl()
  • start_url: a URL inicial de get_home_url()
  • theme_color: um background personalizado de um tema via get_background_color()
  • background_color: também preenchido com o plano de fundo personalizado do tema
  • display: minimal-ui é usada como padrão.
  • icons: Os ícones do site via get_site_icon_url()

Existe um filtro web_app_manifest qual é passado a um array para que os plugins e temas possam personalizar o manifesto.

Veja GitHub issues classificadas e veja o rastreamento de ticket do core do WordPress #43328.

Service Workers

Como observado em Google primer:

Experiências off-line ricas, sincronização periódicas em segundo plano, envio de notificações – funcionalidade que normalmente exigiria um aplicativo nativo – estão chegando à web. Os funcionários de serviço fornecem a base técnica na qual todos esses recursos se baseiam.

Only one service worker can be controlling a page at a time. This has prevented themes and plugins from each introducing their own service workers because only one wins. So the first step at adding support for service workers in core is to provide an API for themes and plugins to register scripts and then have them concatenated into a script that is installed as the service worker. There are two such concatenated service worker scripts that are made available: one for the frontend and one for the admin. The frontend service worker is installed under the home('/') scope and the admin service worker is installed under the admin_url('/') scope.

The API is implemented using the same interface as WordPress uses for registering scripts; in fact WP_Service_Worker_Scripts is a subclass of WP_Scripts. The instance of this class is accessible via wp_service_workers()->get_registry(). Instead of using wp_register_script() the service worker scripts are registered using wp_register_service_worker_script(). This function accepts two parameters:

  • $handle: O identificador de script do service worker que pode ser usado para marcar o script como uma dependência para outros scripts.
  • $args: Um array de argumentos para service worker adicionais como pares $key => $value:
    • $src: Obrigatório: A URL para o service worker no sistema de arquivos local ou uma função de retorno de chamada que retorna o script pra incluir no service worker.
    • $deps: Um array de service worker que lida com qual o script depende.

Note que não há parâmetros (versão) $ver porque browsers não adicionam service workers no cache então não existe a necessidade de limpa-lo.

O script do service worker deve ser registrado nos hooks wp_front_service_worker e/ou wp_admin_service_worker, dependendo do que como eles devem ser ativos para o service worker no front-end e no administrador, ou ambos. Os Hooks são passadas as instâncias do WP_Service_Worker_Scripts, então você pode opcionalmente acessar o método register() diretamente, qual wp_register_service_worker_script() é um simples invólucro.

Aqui alguns exemplos:

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' );

Veja problemas rotulados no GitHub e veja o rastreamento de ticket do core do WordPress #36995.

Integrações

O plugin agrupa várias integrações experimentais que são mantidas separadas do código central do service worker. Essas integrações atual como exemplos e provas de conceitos para atingir os objetivos. Embora todos eles sejam geralmente aplicáveis e recomendados para se beneficiarem verdadeiramente dos service workers, eles não são cruciais para a API principal.

Todas essas integrações são escondidas atrás de uma feature flag. Para habilitar-los, você pode adicionar suporte ao tema com o código service_worker:

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

Alternativamente, você pode através de seleção habilitar integrações específicas provendo um array para suporte do tema:

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

Caching

Os service workers no plug-in de recursos estão usando Workbox para gerar uma abstração PHP de nível superior para temas e plug-ins para indicar as rotas e as estratégias de armazenamento em cache de maneira declarativa. Como apenas um manipulador pode ser usado por uma rota, os conflitos também são detectados e relatados no console ao usar o mode de depuração.

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(): aceita os seguintes parâmetros:
    • $url: URL para cache.
    • $args: Um array de argumentos de rotas adicional como pares $key => $value:
    • $revision: Revisão, opcional.

Exemplos de uso da 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' ),
    )
);

Se você deseja optar por uma estratégia de cache para solicitações de navegação é possível:

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.

Tratamento de Offline/Erro 500

O plugin oferece melhorias na experiência off-line exibindo um template personalizado quando o usuário está off-line, em vez de uma mensagem padrão do navegador. O mesmo vale para erros 500 — um template é exibido junto com os detalhes do erro.

Temas podem sobrescrever o template padrão usado por error.php, offline.php e 500.php na pasta do seu tema. error.php é o template geral para erros tanto off-line quanto paginas de erro 500 e ela sobrescrita por offline.php e 500.php caso existam.

Note que os templates devem usar wp_service_worker_error_message_placeholder() para exibir os mensagens offline/error. Adicionalmente, no template de erro 500 os detalhes do erro pode ser exibidos usando a função wp_service_worker_error_details_template( $output ).

Para propósitos de desenvolvimento os templates para offline e erro 500 são visíveis nas seguintes URLs no seu site:
https://your-site-name.com/?wp_error_template=offline;
https://your-site-name.com/?wp_error_template=500

O valor padrão para $output é o seguinte: ‘ . esc_html__( ‘More Details’, ‘pwa’ ) . ‘{{{error_details_iframe}}} onde {{{error_details_iframe}}} vai ser substituído por um iframe.

Caso use um <iframe> dentro do template {{{iframe_src}}} e {{{iframe_srcdoc}}} também estarão disponíveis.

Por exemplo, isso pode ser feito:

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

Comentando Off-line

Outro recurso que melhora a experiência offline é a possibilidade de implementar Comentários Off-line possibilitado por Workbox Background Sync API.

No caso de envio de comentários quando o usuário estiver off-line(falhando o fetch) o pedido é adicionado a uma fila e uma vez que os navegadores “sabem” que a conectividade voltou o Sync é adicionado e todos os pedidos de comentários na fila são enviados. Isto significa que o comentário será reapresentado uma vez que a conexão esteja disponível novamente.

Ações e filtros disponíveis

Aqui está uma lista de todas as ações e filtros disponíveis adicionados pelo 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.

Ações:
wp_front_service_worker: Dispara antes to service worker ser servido, quando os scripts devem ser registrados, estabelecendo rotas de cache e assets adicionados no cache anteriormente.
– Tem um argumento $script WP_Service_Worker_Scripts Instanciado para definir o comportamento do service worker.
wp_admin_service_worker: Dispara antes do service worker do wp-admin, quando seus scripts devem ser registrados, rotas de cache estabelecidas, e assets adicionados no cache anteriormente.
– Tem um argumento $script WP_Service_Worker_Scripts Instanciado para definir o comportamento do service worker.
wp_default_service_workers: Disparado quando a instância WP_Service_Worker_Scripts é inicializada.
– Tem um argumento $scripts WP_Service_Worker_Scripts Instanciado para definir o comportamento do service worker.

HTTPS

HTTPS é um pre-requisito para progressive web apps. Um service worker pode ser instalado apenas em sites que são servidos com HTTPS. Por esse motivo, o suporte do núcleo ao HTTPS precisa ser melhorado, continuando o grande progresso feito nos últimos anos.

At the moment the plugin provides an API to detection of whether a site supports HTTPS. Building on that it’s intended that this can then be used to present a user with an opt-in to switch over to HTTPS, which will also then need to include support for rewriting URLs from HTTP to HTTPS. See labeled GitHub issues and see WordPress core tracking ticket #28521.

Você pode opcionalmente adicionar um Cabeçalho HSTS (HTTP Strict-Transport-Security). Que indica o browser para somente carregar o site com HTTPS, no 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;
} );

Isso pode impedir um caso em que os usuários acessem inicialmente a versão HTTP do site e sejam redirecionados para um site mal-intencionado antes de um redirecionamento para a versão adequada a HTTPS.

O Filtro wp_headers permite adicionar um cabeçalho Strict-Transport-Security.

Veja a documentação para as diretivas, incluindo o max-age.

Avaliações

24 de janeiro de 2020
I believe PWAs are the future of mobile, I am using this plugin as well as the Drupal PWA module on 3 different sites/apps currently. I like how this uses Workbox and wondering when will support for background sync be included. Very useful and customizable plugin as it is.
10 de outubro de 2019
Biggest speed improvement is when I added navigation pre-load filter: 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; } ); Resulting in sub 200ms page load time! I'm also using it to cache images, css, js. Easy to update manifest as well through filter: function get_manifest_update( $manifest ) { /* $manifest = array( 'name' => wp_kses_decode_entities( get_bloginfo( 'name' ) ), 'start_url' => home_url( '/' ), 'display' => 'minimal-ui', 'dir' => is_rtl() ? 'rtl' : 'ltr', ); */ // Add argument to $manifest array $manifest['start_url'] .= 'en/page/support/'; $manifest['short_name'] = 'My App'; $manifest['name'] = 'Full name of app'; return $manifest; } add_filter( 'web_app_manifest', 'get_manifest_update' ); Hopefully this will be added to WP core soon! Thanks for making it easy to implement service workers with hooks as well, great way to introduce Devs to PWA!
19 de dezembro de 2018
Currently this is a pain to manage. Great effort and hopefully will be merged sooner rather than later!
12 de dezembro de 2018
tienes que hacer el manifiesto y tienes que hacer el service worker entonces cual es el chiste!!! muy mal plugin
Leia todas as 7 avaliações

Contribuidores e desenvolvedores

“PWA” é um software com código aberto. As seguintes pessoas contribuíram para este plugin.

Contribuidores

“PWA” foi traduzido para 4 localidades. Agradecemos aos tradutores por suas contribuições.

Traduzir “PWA” para o seu idioma.

Interessado no desenvolvimento?

Navegue pelo código, dê uma olhada no repositório SVN ou assine o registro de desenvolvimento via RSS.

Registro de alterações

Para acompanhar os logs de mudanças do plugin acesse a página de Releases no GitHub.