aboutsummaryrefslogtreecommitdiff
path: root/files/pt-br/web/api/service_worker_api
diff options
context:
space:
mode:
authorPeter Bengtsson <mail@peterbe.com>2020-12-08 14:42:52 -0500
committerPeter Bengtsson <mail@peterbe.com>2020-12-08 14:42:52 -0500
commit074785cea106179cb3305637055ab0a009ca74f2 (patch)
treee6ae371cccd642aa2b67f39752a2cdf1fd4eb040 /files/pt-br/web/api/service_worker_api
parentda78a9e329e272dedb2400b79a3bdeebff387d47 (diff)
downloadtranslated-content-074785cea106179cb3305637055ab0a009ca74f2.tar.gz
translated-content-074785cea106179cb3305637055ab0a009ca74f2.tar.bz2
translated-content-074785cea106179cb3305637055ab0a009ca74f2.zip
initial commit
Diffstat (limited to 'files/pt-br/web/api/service_worker_api')
-rw-r--r--files/pt-br/web/api/service_worker_api/index.html322
-rw-r--r--files/pt-br/web/api/service_worker_api/using_service_workers/index.html522
2 files changed, 844 insertions, 0 deletions
diff --git a/files/pt-br/web/api/service_worker_api/index.html b/files/pt-br/web/api/service_worker_api/index.html
new file mode 100644
index 0000000000..05ae2f90c8
--- /dev/null
+++ b/files/pt-br/web/api/service_worker_api/index.html
@@ -0,0 +1,322 @@
+---
+title: API do Service Worker
+slug: Web/API/Service_Worker_API
+translation_of: Web/API/Service_Worker_API
+---
+<p>{{ServiceWorkerSidebar}} </p>
+
+<p class="summary">Essencialmente, um <em>service worker</em> se comporta como um servidor <em>proxy</em> situado entre uma aplicação web, o navegador e a rede (quando esta estiver disponível). Eles servem, dentre outras coisas, para possibilitar a criação de experiências <em>offline</em> eficientes, interceptar requisições de rede – agindo adequadamente de acordo com o <em>status</em> atual da conexão – e atualizar os <em>assets</em> que residem no servidor. Service workers também permitem o acesso às APIs de <em>push notification</em> e <em>background sync</em>. </p>
+
+<h2 id="Service_worker_-_Conceitos_e_uso">Service worker - Conceitos e uso</h2>
+
+<p>Um <em>service worker</em> é um tipo especial de <em><a href="https://developer.mozilla.org/pt-BR/docs/Web/API/Worker">worker</a></em> baseado em eventos, o qual é registrado para um determinado <em>path</em> e origem. Na prática, ele é um arquivo JavaScript que pode controlar as páginas do site ao qual ele está associado, interceptando e modificando requisições e a navegação em si. Ele também faz <em>cache</em> dos recursos trafegados de maneira bastante granular, visando oferecer controle total sobre como a sua aplicação se comporta em determinadas situações (o exemplo mais óbvio, naturalmente, é quando não há conexão de rede disponível).</p>
+
+<p>Assim como outros tipos de <em>worker</em>, um <em>service worker</em> é executado em um contexto isolado. Dessa forma, não tem acesso ao DOM e roda em uma thread completamente separada, sendo incapaz de realizar operações blocantes. Service workers foram projetados para ser totalmente assíncronos; como consequência disso, não permitem o acesso a APIs como <a href="https://developer.mozilla.org/pt-BR/docs/Web/API/XMLHttpRequest/Requisicoes_sincronas_e_assincronas#Synchronous_request">XHR síncrono</a> e <a href="https://developer.mozilla.org/pt-BR/docs/Web/API/Window/Window.localStorage">localStorage</a>.  </p>
+
+<p>Por questões de segurança, <em>service workers</em> funcionam apenas em sites servidos via HTTPS. A possibilidade de modificar requisições em um domínio desprotegido contra ataques do tipo <a href="https://developer.mozilla.org/en-US/docs/Glossary/MitM">man-in-the-middle</a> seria desastrosa. No Firefox, é vetado o acesso à API de <em>service workers</em> para sites abertos no <a href="https://support.mozilla.org/pt-BR/kb/navegacao-privativa-use-firefox-sem-historico">Modo de navegação privativa</a>.</p>
+
+<div class="note">
+<p><strong>Nota:</strong> Os service workers superaram tentativas anteriores de resolver problemas semelhantes, como o <a href="http://alistapart.com/article/application-cache-is-a-douchebag">AppCache</a>. Há uma explicação simples para eles terem sido bem-sucedidos: Service workers <strong>não</strong> tentam adivinhar o que você está tentando fazer e, muito menos, deixam de funcionar caso não tenham adivinhado corretamente. Pelo contrário, você tem o controle milimétrico de tudo.    </p>
+</div>
+
+<div class="note">
+<p><strong>Nota:</strong> Service workers fazem uso intenso de <a href="https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Promise">promessas</a>, uma vez que eles têm de esperar por respostas assíncronas para, após retornadas, poderem executar a ação apropriada (de sucesso ou erro). A arquitetura de promessas é ideal para esse tipo de cenário.</p>
+</div>
+
+<p> </p>
+
+<h3 id="Registrando">Registrando</h3>
+
+<p>O registro inicial de um <em>service worker</em> é feito através do método {{domxref("ServiceWorkerContainer.register()")}}. Se bem-sucedido, seu <em>service worker</em> será descarregado no cliente e então ocorrerá a tentativa de instalação/ativação para as URLs acessadas pelo usuário sob a origem registrada ou, caso deseje, apenas dentro de um subconjunto limitado por você.</p>
+
+<h3 id="Download_instalação_e_ativação">Download, instalação e ativação</h3>
+
+<p>Nesse estágio, seu service worker seguirá o seguinte ciclo de vida:</p>
+
+<ol>
+ <li>Download</li>
+ <li>Instalação</li>
+ <li>Ativação</li>
+</ol>
+
+<p>Quando o usuário acessa pela primeira vez um site ou página controlado por um service worker, ele é descarregado imediatamente.</p>
+
+<p>Após isso, serão feitos novos downloads em intervalos de aproximadamente 24 horas. O download <strong>pode</strong> ocorrer mais frequentemente, mas ele <strong>precisa</strong> ser feito a cada 24 horas para prevenir que scripts ruins sejam um problema por períodos muito extensos. </p>
+
+<p>A tentativa de instalação é feita sempre que o arquivo descarregado é identificado como novo – seja por diferir dos <em>service workers</em> pré-existentes (é feita uma comparação binária nessa etapa) ou por ser o primeiro descoberto para a página ou site em questão.</p>
+
+<p>Na primeira vez que um <em>service worker</em> é disponibilizado, é feita a tentativa de instalação. Se bem-sucedida, ele é ativado.</p>
+
+<p>Se, por outro lado, já existe um <em>service worker</em> pré-instalado para uma página ou site e for disponibilizada uma nova versão, ela será descarregada, mas não imediatamente ativada. Isso é chamado de <strong><em>worker</em> em espera</strong>. Só será efetuada a ativação da versão atualizada quando não houver mais páginas utilizando a anterior. Após isso, ele passa a ser o <strong><em>worker</em> ativo</strong>. Caso necessário, é possível pular a etapa de espera com o método {{domxref("ServiceWorkerGlobalScope.skipWaiting()")}}. Em seguida, o novo worker ativo pode reivindicar as páginas existentes usando {{domxref("Clients.claim()")}}. </p>
+
+<p>Você pode adicionar um <em>listener</em> para o evento {{domxref("InstallEvent")}}. Uma ação padrão, quando esse evento é disparado, é preparar o seu <em>service worker</em> para ser utilizado (por exemplo: criado um cache usando a API de storage nativa e armazenando nela os <em>assets</em> que você quer que permaneçam disponíveis caso a aplicação fique <em>offline</em>).</p>
+
+<p>Há também o evento <code>activate</code>. O momento em que ele é disparado é geralmente o ideal para limpar caches antigos e outras coisas associadas com a versão anterior do seu <em>service worker</em>.</p>
+
+<p>Seu service worker pode responder a requisições usando o {{domxref("FetchEvent")}}. Você pode manipular a resposta a essas requisições da maneira que quiser, através do método {{domxref("FetchEvent.respondWith")}}.</p>
+
+<div class="note">
+<p><strong>Nota: </strong>Como <code>oninstall<font face="x-locale-heading-primary, zillaslab, Palatino, Palatino Linotype, x-locale-heading-secondary, serif"><span style="background-color: #fff3d4; font-size: 18px;"> e </span></font></code><code>onactivate</code> podem demorar a serem concluídos, a especificação de <em>service workers</em> disponibiliza um método <a href="https://developer.mozilla.org/en-US/docs/Web/API/ExtendableEvent/waitUntil">waitUntil</a>. Ele recebe como parâmetro uma <a href="https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Promise">promessa</a>, notificando o navegador que há trabalho em andamento até que aquela promessa seja resolvida. O navegador, portanto, não deverá encerrar o service worker durante esse período de espera. </p>
+</div>
+
+<p>Para um tutorial completo, mostrando como construir seu primeiro exemplo do zero, leia <a href="https://developer.mozilla.org/pt-BR/docs/Web/API/Service_Worker_API/Using_Service_Workers">Usando Service Workers</a>.</p>
+
+<h2 id="Outras_ideias_de_usos_possíveis">Outras ideias de usos possíveis</h2>
+
+<ul>
+ <li>Sincronização de dados em <em>background</em></li>
+ <li>Responder a requisições de recursos a partir de outras origens</li>
+ <li>Receber de forma centralizada atualizações para dados de cálculo mais custoso, como geolocalização ou giroscópio, de forma a permitir que múltiplas páginas façam uso de um único conjunto de dados.</li>
+ <li>No lado do cliente, fazer compilação e gerenciamento de dependências para CoffeeScript, LESS, módulos CommonJS/AMD, entre outros.  </li>
+ <li><em>Hooks</em> para serviços em <em>background</em>.</li>
+ <li>Templates customizados com base em certos padrões de URL.</li>
+ <li>Melhorias de performance como, por exemplo, fazer o pré-carregamento de recursos que o usuário provavelmente irá precisar a curto prazo, como as próximas fotos de um álbum.</li>
+</ul>
+
+<p>No futuro, service workers serão capazes de fazer várias outras coisas úteis para a plataforma web, deixando-a mais próxima de <em>apps</em> nativos em.</p>
+
+<p>É interessante mencionar que outras especificações podem e irão passar a usar o contexto de service workers, por exemplo:</p>
+
+<ul>
+ <li><a href="https://github.com/WICG/BackgroundSync">Sincronização em background</a>: Iniciar um service worker mesmo quando não há usuários no site, de forma que o cache possa ser atualizado;</li>
+ <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Push_API">Reagir a mensagens push</a>: Iniciar um service worker para enviar uma mensagem aos usuários dizendo que há conteúdo novo disponível;</li>
+ <li>Reagir a uma data/hora específica;</li>
+ <li>Entrar em uma <a href="https://en.wikipedia.org/wiki/Geo-fence">geo-fence</a>.</li>
+</ul>
+
+<h2 id="Interfaces">Interfaces</h2>
+
+<dl>
+ <dt>{{domxref("Cache")}}</dt>
+ <dd>Representa o armazenamento para os pares de objeto {{domxref("Request")}} e {{domxref("Response")}}, os quais são cacheados como parte do ciclo de vida do {{domxref("ServiceWorker")}}.</dd>
+ <dt>{{domxref("CacheStorage")}}</dt>
+ <dd>Representa o armazenamento para objetos {{domxref("Cache")}}. Ele disponibiliza um diretório-mestre com todos os caches nomeados que um {{domxref("ServiceWorker")}} pode acessar, mantendo o mapeamento de nomes para os objetos {{domxref("Cache")}} correspondentes.</dd>
+ <dt>{{domxref("Client")}}</dt>
+ <dd>Representa o escopo do cliente de um <em>service worker</em>. Um cliente pode ser um documento no contexto de um navegador ou um {{domxref("SharedWorker")}}, o qual é controlado por um <em>worker</em> ativo.</dd>
+ <dt>{{domxref("Clients")}}</dt>
+ <dd>Representa o container para uma lista de objetos {{domxref("Client")}}. É a principal forma de acessar os clientes na origem atual para o <em>service worker</em> ativo.</dd>
+ <dt>{{domxref("ExtendableEvent")}}</dt>
+ <dd>Estende a vida dos eventos <code>install</code> e <code>activate</code> disparados no {{domxref("ServiceWorkerGlobalScope")}}, como parte do ciclo de vida do <em>service worker</em>. Isso garante que qualquer evento funcional (como o {{domxref("FetchEvent")}}) não seja despachado para o {{domxref("ServiceWorker")}} até que ele conclua as ações em andamento, como por exemplo: atualizar esquemas de banco de dados, apagar caches defasados, etc.</dd>
+ <dt>{{domxref("ExtendableMessageEvent")}}</dt>
+ <dd>O objeto de evento do {{event("message_(ServiceWorker)","message")}}, o qual é disparado em um <em>service worker </em>(quando uma mensagem de canal é recebida no {{domxref("ServiceWorkerGlobalScope")}} a partir de outro contexto) — estende o tempo de vida desses eventos.</dd>
+ <dt>{{domxref("FetchEvent")}}</dt>
+ <dd>O parâmetro recebido no <em>handler</em>  {{domxref("ServiceWorkerGlobalScope.onfetch")}}. O <code>FetchEvent</code> representa uma ação de descarregamento que é despachada no {{domxref("ServiceWorkerGlobalScope")}} de um  {{domxref("ServiceWorker")}}. Ele contém informações sobre a requisição e a resposta resultante, além de disponibilizar o método {{domxref("FetchEvent.respondWith", "FetchEvent.respondWith()")}}, o qual nos permite devolver uma resposta customizada para a página que está sendo controlada.</dd>
+ <dt>{{domxref("InstallEvent")}}</dt>
+ <dd>O parâmetro recebido no <em>handler</em>  {{domxref("ServiceWorkerGlobalScope.oninstall", "oninstall")}}. A interface <code>InstallEvent</code> representa uma ação de instalação que é despachada no {{domxref("ServiceWorkerGlobalScope")}} de um  {{domxref("ServiceWorker")}}. Como deriva do {{domxref("ExtendableEvent")}}, ele assegura que eventos funcionais, como o {{domxref("FetchEvent")}}, não sejam despachados durante a instalação. </dd>
+ <dt>{{domxref("NavigationPreloadManager")}}</dt>
+ <dd>Disponibiliza métodos para gerenciar o pré-carregamento de recursos com um <em>service worker.</em> </dd>
+ <dt>{{domxref("Navigator.serviceWorker")}}</dt>
+ <dd>Retornar um objeto {{domxref("ServiceWorkerContainer")}}, o qual permite accesso ao registro, remoção, atualização e comunicação com os objetos {{domxref("ServiceWorker")}} para o <a href="https://html.spec.whatwg.org/multipage/browsers.html#concept-document-window">documento associado</a>.</dd>
+ <dt>{{domxref("NotificationEvent")}}</dt>
+ <dd>O parâmetro recebido no <em>handler</em>  {{domxref("ServiceWorkerGlobalScope.onnotificationclick", "onnotificationclick")}}. A interface <code>NotificationEvent</code> representa um evento de <em>click</em> em uma notificação que é despachado no {{domxref("ServiceWorkerGlobalScope")}} de um {{domxref("ServiceWorker")}}.</dd>
+ <dt>{{domxref("ServiceWorker")}}</dt>
+ <dd>Representa um <em>service worker</em>. Diferentes contextos de navegação (ex: páginas, <em>workers</em>, etc.) podem ser associados com o mesmo objeto <code>ServiceWorker</code>.</dd>
+ <dt>{{domxref("ServiceWorkerContainer")}}</dt>
+ <dd>Disponibiliza um objeto representando o service worker como uma unidade global no ecossistema de rede, incluindo métodos para registrar, desregistrar e atualizar <em>service workers</em>, além de poder acessar o status de cada <em>worker</em> e seus registros.</dd>
+ <dt>{{domxref("ServiceWorkerGlobalScope")}}</dt>
+ <dd>Representa o contexto de execução global de um <em>service worker</em>.</dd>
+ <dt>{{domxref("ServiceWorkerMessageEvent")}} {{deprecated_inline}}</dt>
+ <dd>Representa uma mensagem enviada a um {{domxref("ServiceWorkerGlobalScope")}}. <strong>Vale ressaltar que essa interface está defasada em navegadores modernos. As mensagens de <em>service worker</em> agora usam a interface {{domxref("MessageEvent")}} para manter consistência com outras funcionalidades de messageria da web.</strong></dd>
+ <dt>{{domxref("ServiceWorkerRegistration")}}</dt>
+ <dd>Representa o registro de um <em>service worker</em>.</dd>
+ <dt>{{domxref("ServiceWorkerState")}} {{experimental_inline}}</dt>
+ <dd>Associado com o estado do <a href="https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorker" title="The ServiceWorker interface of the ServiceWorker API provides a reference to a service worker. Multiple browsing contexts (e.g. pages, workers, etc.) can be associated with the same service worker, each through a unique ServiceWorker object."><code>ServiceWorker</code></a>.</dd>
+ <dt>{{domxref("SyncEvent")}} {{non-standard_inline}}</dt>
+ <dd>
+ <p>A interface SyncEvent representa uma ação de sincronização que é despachada no {{domxref("ServiceWorkerGlobalScope")}} de um ServiceWorker. </p>
+ </dd>
+ <dt>{{domxref("SyncManager")}} {{non-standard_inline}}</dt>
+ <dd>Disponibiliza uma interface para registrar e listar registros de sincronização.</dd>
+ <dt>{{domxref("WindowClient")}}</dt>
+ <dd>Representa o escopo de um cliente de <em>service worker</em> que é um documento em um contexto de navegador, o qual é controlado por um <em>worker</em> ativo. Esse é um tipo especial de objeto {{domxref("Client")}}, como alguns métodos e propriedades adicionais disponíveis.</dd>
+</dl>
+
+<h2 id="Especificações">Especificações</h2>
+
+<table>
+ <tbody>
+ <tr>
+ <th scope="col">Especificação</th>
+ <th scope="col">Status</th>
+ <th scope="col">Comentário</th>
+ </tr>
+ <tr>
+ <td>{{SpecName('Service Workers')}}</td>
+ <td>{{Spec2('Service Workers')}}</td>
+ <td>Initial definition.</td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="Compatibilidade_de_Navegador">Compatibilidade de Navegador</h2>
+
+<p>{{ CompatibilityTable() }}</p>
+
+<table>
+ <tbody>
+ <tr>
+ <th>Recurso</th>
+ <th>Chrome</th>
+ <th>Edge</th>
+ <th>Firefox (Gecko)</th>
+ <th>Internet Explorer</th>
+ <th>Opera</th>
+ <th>Safari (WebKit)</th>
+ </tr>
+ <tr>
+ <td>Suporte básico</td>
+ <td>{{CompatChrome(40)}}</td>
+ <td>{{CompatNo}}<sup>[1]</sup></td>
+ <td>{{ CompatGeckoDesktop("44.0") }}<sup>[2]</sup></td>
+ <td>{{ CompatNo() }}</td>
+ <td>24</td>
+ <td>{{ CompatNo() }}<sup>[3]</sup></td>
+ </tr>
+ <tr>
+ <td>Eventos install/activate</td>
+ <td>{{ CompatChrome(40) }}</td>
+ <td>{{CompatNo}}<sup>[1]</sup></td>
+ <td>{{ CompatGeckoDesktop("44.0") }}<sup>[2]</sup></td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatVersionUnknown() }}</td>
+ <td>{{ CompatNo() }}</td>
+ </tr>
+ <tr>
+ <td>Evento fetch/request/<br>
+ <code>respondWith()</code></td>
+ <td>{{CompatChrome(40)}}</td>
+ <td>{{CompatNo}}<sup>[1]</sup></td>
+ <td>{{ CompatGeckoDesktop("44.0") }}<sup>[2]</sup></td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatNo() }}</td>
+ </tr>
+ <tr>
+ <td>caches/cache</td>
+ <td>
+ <p>{{CompatChrome(42)}}</p>
+ </td>
+ <td>{{CompatNo}}<sup>[1]</sup></td>
+ <td>{{ CompatGeckoDesktop("39.0") }}<sup>[2]</sup></td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatNo() }}</td>
+ </tr>
+ <tr>
+ <td>{{domxref("ServiceWorkerMessageEvent")}} defasado em favor {{domxref("MessageEvent")}}</td>
+ <td>
+ <p>{{CompatChrome(57)}}</p>
+ </td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatGeckoDesktop("55.0") }}<sup>[2]</sup></td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatNo() }}</td>
+ </tr>
+ <tr>
+ <td><code>NavigationPreloadManager</code></td>
+ <td>{{CompatChrome(59)}}</td>
+ <td>{{ CompatNo() }}</td>
+ <td> </td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{CompatOpera(46)}}</td>
+ <td>{{ CompatNo() }}</td>
+ </tr>
+ </tbody>
+</table>
+
+<table>
+ <tbody>
+ <tr>
+ <th>Recursos</th>
+ <th>Android Webview</th>
+ <th>Chrome for Android</th>
+ <th>Edge</th>
+ <th>Firefox Mobile (Gecko)</th>
+ <th>IE Phone</th>
+ <th>Opera Mobile</th>
+ <th>Safari Mobile</th>
+ </tr>
+ <tr>
+ <td>Suporte básico</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{CompatChrome(40)}}</td>
+ <td>{{CompatNo}}<sup>[1]</sup></td>
+ <td>{{ CompatGeckoMobile("44.0") }}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatVersionUnknown() }}</td>
+ <td>{{ CompatNo() }}<sup>[3]</sup></td>
+ </tr>
+ <tr>
+ <td>Eventos install/activate</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{CompatChrome(40)}}</td>
+ <td>{{CompatNo}}<sup>[1]</sup></td>
+ <td>{{ CompatGeckoMobile("44.0") }}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatVersionUnknown() }}</td>
+ <td>{{ CompatNo() }}</td>
+ </tr>
+ <tr>
+ <td>Evento fetch/request/<br>
+ <code>respondWith()</code></td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{CompatChrome(40)}}</td>
+ <td>{{CompatNo}}<sup>[1]</sup></td>
+ <td>{{ CompatGeckoMobile("44.0") }}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatNo() }}</td>
+ </tr>
+ <tr>
+ <td>caches/cache</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{CompatChrome(40)}}</td>
+ <td>{{CompatNo}}<sup>[1]</sup></td>
+ <td>{{ CompatGeckoMobile("39.0") }}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatNo() }}</td>
+ </tr>
+ <tr>
+ <td>{{domxref("ServiceWorkerMessageEvent")}} defasado em favor de {{domxref("MessageEvent")}}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>
+ <p>{{CompatChrome(57)}}</p>
+ </td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatGeckoMobile("55.0") }}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatNo() }}</td>
+ </tr>
+ <tr>
+ <td><code>NavigationPreloadManager</code></td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{CompatChrome(59)}}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{ CompatNo() }}</td>
+ <td>{{CompatOperaMobile(46)}}</td>
+ <td>{{ CompatNo() }}</td>
+ </tr>
+ </tbody>
+</table>
+
+<p>[1] Esse recurso ainda não é suportado, apesar de <a href="https://developer.microsoft.com/en-us/microsoft-edge/platform/status/serviceworker/">já estar em desenvolvimento</a>.</p>
+
+<p>[2] Service workers (e <a href="https://developer.mozilla.org/en-US/docs/Web/API/Push_API">Push</a>) foram desabilitados no Firefox, nas versões <a href="https://www.mozilla.org/en-US/firefox/organizations/">45 &amp; 52 Extended Support Releases</a> (ESR.)</p>
+
+<p>[3] Esse recurso ainda não é suportado, apesar de <a href="https://bugs.webkit.org/show_bug.cgi?id=174541">já estar em desenvolvimento</a>.</p>
+
+<h2 id="Veja_também">Veja também</h2>
+
+<ul>
+ <li><a href="https://serviceworke.rs/">ServiceWorker Cookbook</a></li>
+ <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorker_API/Using_Service_Workers">Using Service Workers</a></li>
+ <li><a href="https://github.com/mdn/sw-test">Service workers basic code example</a></li>
+ <li><a href="https://jakearchibald.github.io/isserviceworkerready/">Is ServiceWorker ready?</a></li>
+ <li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promises</a></li>
+ <li><a href="https://developer.mozilla.org/en-US/docs/Web/Guide/Performance/Using_web_workers">Using web workers</a></li>
+ <li><a href="https://www.fastly.com/blog/best-practices-for-using-the-vary-header">Best Practices for using the VARY header</a></li>
+</ul>
diff --git a/files/pt-br/web/api/service_worker_api/using_service_workers/index.html b/files/pt-br/web/api/service_worker_api/using_service_workers/index.html
new file mode 100644
index 0000000000..983b352d82
--- /dev/null
+++ b/files/pt-br/web/api/service_worker_api/using_service_workers/index.html
@@ -0,0 +1,522 @@
+---
+title: Usando Service Workers
+slug: Web/API/Service_Worker_API/Using_Service_Workers
+translation_of: Web/API/Service_Worker_API/Using_Service_Workers
+---
+<p>{{ServiceWorkerSidebar}}</p>
+
+<p>{{ SeeCompatTable() }}</p>
+
+<div class="summary">
+<p>Esse artigo contém informações de como começar com service workers, incluindo a arquitetura básica, registro de um service worker, o processo de instalação e ativação de um novo service worker, atualização de seu service worker, controle de cache e respostas customizadas, tudo isso no contexto de um simples app com a funcionalidade offline.</p>
+</div>
+
+<h2 id="A_premissa_dos_Service_Workers">A premissa dos Service Workers</h2>
+
+<p>O principal problema que os usuários da web sofreram durante anos foi a perda de conexão. Até mesmo melhor web app do mundo terá uma péssima experiência de usuário se você não conseguir baixa-lá. Houveram várias tentativas de criar tecnologias para resolver esse problema, como mostra nossa página <a href="/en-US/Apps/Build/Offline">Offline</a>, e algumas questões foram resolvidas. Mas o maior problema é que, no geral, ainda não há um bom mecanismo de controle para caching de assets e requisições de rede personalizadas.<br>
+ <br>
+ A tentativa anterior — <a href="https://developer.mozilla.org/pt-BR/docs/Web/HTML/Using_the_application_cache">AppCache</a> — parecia uma boa ideia, pois permitia especificar facilmente os assets para cache. Porém, fazia várias suposições sobre o que você estava tentando fazer e depois quebrava horrivelmente quando seu app não seguia exatamente tais suposições. Leia <a href="http://alistapart.com/article/application-cache-is-a-douchebag">Application Cache is a Douchebag</a> de Jake Archibald para mais detalhes.</p>
+
+<div class="note">
+<p><strong>Nota</strong>: A partir do Firefox 44, quando <a href="/en-US/docs/Web/HTML/Using_the_application_cache">AppCache</a> é usado para fornecer suporte offline  uma página, um aviso é exibido no console para que os desenvolvedores usem <a href="/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers">Service workers</a> ({{bug("1204581")}}.)</p>
+</div>
+
+<p>Service workers devem finalmente corrigir esses problemas. A sintaxe do service worker é mais complexa do que a do AppCache, mas a vantagem é que você pode usar Javascript para controlar os comportamentos implícitos do AppCache com um bom grau de granularidade, permitindo que você lide com esse problema e muitos outros. Usando Service Worker você pode facilmente configurar um app para usar primeiro assets em cache, provendo uma experiência padronizada mesmo que esteja offline, antes de obter mais dados da rede (mais conhecido como <a href="http://offlinefirst.org/">Offline First</a>). Isso já está disponível em apps nativos, que é uma das principais razões pelas quais apps nativos são frequentemente mais escolhidos do que web apps.</p>
+
+<h2 id="Configuração_para_usar_service_workers">Configuração para usar service workers</h2>
+
+<p>Várias características de service workers estão habilitadas por padrão em versões mais recentes dos navegadores suportados. Se, no entanto, encontrar um código de demonstração que não está funcionando na suas versões instaladas, você precisará habilitar essa preferência:</p>
+
+<ul>
+ <li><strong>Firefox Nightly</strong>: Vá para sobre: config e mude <code>dom.serviceWorkers.enabled para true; reinicie o browser.</code></li>
+ <li><strong>Chrome Canary</strong>: Vá para <code>chrome://flags e mude para experimental-web-platform-features; reinicie o navegador (note que alguns recursos do Chrome vem habilitados por padrão.)</code></li>
+ <li><strong>Opera</strong>:  Vá em <code>opera://flags e habilite Support for ServiceWorker; reinicie o navegador.</code></li>
+ <li><strong>Microsoft Edge</strong>: Vá para <code>about:flags</code> and marque <code>Enable service workers</code>; reinicie o navegador.</li>
+</ul>
+
+<p>Você também precisa fornecer seu código via HTTPS — Service workers estão restritos a rodar apenas via HTTPS por motivos de segurança. GitHub serve como um bom host para os experimentos, pois suporta HTTPS. Para facilitar o desenvolvimento local, localhost também é considerado uma origem segura pelos navegadores. </p>
+
+<h2 id="Arquitetura_Básica">Arquitetura Básica</h2>
+
+<p>Com service workers, os seguintes passos geralmente são observados como configuração básica:</p>
+
+<ol>
+ <li>A URL do service worker é buscada e registrada via {{domxref("serviceWorkerContainer.register()")}}.</li>
+ <li>Em caso de sucesso, o service worker é executado em um {{domxref("ServiceWorkerGlobalScope") }}; isto é basicamente um tipo especial de contexto do worker, que é executado fora da thread de execução do script principal, sem acesso ao DOM.</li>
+ <li>O service worker agora está pronto para processar eventos.</li>
+ <li>A tentativa de instalação do worker acontece quando as páginas controladas pelo service worker são acessadas. O evento de instalação é sempre o primeiro a ser enviado ao service worker (isto pode ser usado para iniciar o processode preencher um IndexedDB, e armazenar em cache os assets do site). Este é realmente o mesmo tipo de procedimento para instalação de um aplicativo nativo ou do Firefox OS — disponibilizando tudo offline.</li>
+ <li>Quando o manipulador <code>oninstall </code>estiver completo, considera-se que o service worker está instalado.</li>
+ <li>O próximo é a ativação. Quando um service worker é instalado, ele recebe um evento de ativação. O uso primário do <code>onactivate é</code> para limpeza de recursos usado em versões anterioires do script de um Service worker.</li>
+ <li>O Service worker agora vai controlar páginas, mas apenas aquelas abertas após o <code>register() </code>tiver sido bem-sucedido. Isto é, um documento inicia a vida com ou sem Service worker e mantém isso durante seu tempo de vida. Logo, documentos terão de ser recarregados para serem controlados.</li>
+</ol>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/12636/sw-lifecycle.png" style="display: block; height: 867px; margin: 0px auto; width: 579px;"></p>
+
+<p>O gráfico abaixo mostra um resumo dos eventos de service worker disponíveis:</p>
+
+<p><img alt="install, activate, message, fetch, sync, push" src="https://mdn.mozillademos.org/files/12632/sw-events.png" style="display: block; margin: 0px auto;"></p>
+
+<h3 id="Promises">Promises</h3>
+
+<p><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promises</a> são um ótimo mecanismo para executar operações assíncronas, onde o sucesso de uma depende do sucesso das outras. Isto é o fundamento para o modo como os service workers trabalham.<br>
+ <br>
+ Promises pode fazer uma variedade de coisas, mas tudo o que precisa saber agora é que, se algo retorna uma promise, você pode inserir <code>.then()</code> ao final e incluir dentro dela callback para casos de sucesso ou poder inserir <code>.catch() </code>ao final, se quiser incluir um callback para falha.</p>
+
+<p>Vamos comparar a estrutura de um callback tradicional síncrono para uma promise assíncrona equivalente.</p>
+
+<h4 id="sync">sync</h4>
+
+<pre class="brush: js notranslate">try {
+ var value = myFunction();
+ console.log(value);
+} catch(err) {
+ console.log(err);
+}</pre>
+
+<h4 id="async">async</h4>
+
+<pre class="brush: js notranslate">myFunction().then(function(value) {
+ console.log(value);
+}).catch(function(err) {
+ console.log(err);
+});</pre>
+
+<p>No primeiro exemplo, temos que esperar <code>myFunction()</code> executar e retornar <code>value</code> antes que qualquer código adicional possa ser executado. No segundo exemplo, <code>myFunction()</code> retorna uma promessa para <code>value</code>, então o resto do código pode ser executado logo em seguida. Quando a promessa é atendida, o código dentro do método <code>then</code> será executado, assincronamente.<br>
+ <br>
+ Agora para um exemplo real — e se quiséssemos carregar imagens dinamicamente, mas quiséssemos ter certeza que as imagens estão carregadas antes de tentar mostrá-las? É uma coisa padrão que estamos querendo fazer, mas pode ser um pouco complicado. Podemos usar <code>.onload</code> para somente mostrar a imagem após ela ter carregado, mas e para os eventos que aconteceram antes de começarmos a ouvi-los? Podemos tentar contornar isso usando <code>.complete</code>, mas ainda não é a prova de falhas, e para várias imagens? E, ummm, ainda é síncrono, portanto bloqueia a thread principal.<br>
+ <br>
+ Ao invés disso, podemos contruir nossa própria promessa para lidar com casos deste tipo. (Veja o exemplo <a href="https://github.com/mdn/js-examples/tree/master/promises-test">Promises test</a> para o código fonte, ou <a href="https://mdn.github.io/promises-test/">veja rodando live</a>.)</p>
+
+<p>{{note("Uma implementação real de service worker usaria caching e onfetch ao invés da depreciada XMLHttpRequest API. Estes features não são usados aqui para que você foque em entender Promises.")}}</p>
+
+<pre class="brush: js notranslate">function imgLoad(url) {
+ return new Promise(function(resolve, reject) {
+ var request = new XMLHttpRequest();
+ request.open('GET', url);
+ request.responseType = 'blob';
+
+ request.onload = function() {
+ if (request.status == 200) {
+ resolve(request.response);
+ } else {
+ reject(Error('Image didn\'t load successfully; error code:' + request.statusText));
+ }
+ };
+
+ request.onerror = function() {
+ reject(Error('There was a network error.'));
+ };
+
+ request.send();
+ });
+}</pre>
+
+<p>Retornamos uma nova promise usando o <code>Promise()</code> constructor, o qual tem uma função callback como argumento com os parâmetros <code>resolve</code> e<code>reject</code>. Em algum lugar na função, precisamos definir o que acontece para que a promessa ser resolvida com sucesso ou ser rejeitada — neste caso, retornar um status 200 OK ou não — e então chamar <code>resolve</code> em caso de sucesso, ou <code>reject</code> em caso de falha. O resto do conteúdo desta função é XHR padrão, então, não vamos nos preocupar com isso agora.</p>
+
+<p>Quando chamamos a função <code>imgLoad()</code>, chamamos com a url para a imagem que queremos carregar, como seria de se esperar, mas o resto do código é um pouco diferente:</p>
+
+<pre class="brush: js notranslate">var body = document.querySelector('body');
+var myImage = new Image();
+
+imgLoad('myLittleVader.jpg').then(function(response) {
+ var imageURL = window.URL.createObjectURL(response);
+ myImage.src = imageURL;
+ body.appendChild(myImage);
+}, function(Error) {
+ console.log(Error);
+});</pre>
+
+<p>No fim da chamada da função, encadeamos o método <code>then()</code> da promisse, o qual contém duas funções — a primeira é executada quando a promisse é resolvida com sucesso, e a segunda é chamada quando a promise é rejeitada. Caso seja resolvida, exibimos a imagem dentro de <code>myImage</code> e a acrescentamos ao corpo (cujo argument é o <code>request.response</code> contido dentro do método <code>resolve</code> da promise); no caso de rejeição, nos retornamos um erro ao console.</p>
+
+<p>Tudo isto acontece assincronamente.</p>
+
+<div class="note">
+<p><strong>Nota</strong>: Você também pode encadear chamadas de promises, por exemplo:<br>
+ <code>myPromise().then(success, failure).then(success).catch(failure);</code></p>
+</div>
+
+<div class="note">
+<p><strong>Nota</strong>: Você pode encontrar muito mais informações sobre promises lendo o excelente <a href="http://www.html5rocks.com/en/tutorials/es6/promises/">JavaScript Promises: there and back again</a> de Jake Archibald.</p>
+</div>
+
+<h2 id="Demonstração_de_Service_workers">Demonstração de Service workers</h2>
+
+<p>Para demonstrar apenas o básico de registro e instalação de um service worker, criamos uma simples demonstração chamada <a href="https://github.com/mdn/sw-test">sw-test</a>, que é uma simples galeria de imagens de Star Wars Lego. Usa uma função ativada por promise para ler dados de imagem a partir de um objeto JSON e carrega as imagens usando Ajax, antes de exibir as imagens em uma linha ao longo da página. Mantivemos as coisas estáticas e simples por enquanto. Também registra, instala e ativa um service worker, e quando mais especificações são suportadas pelos navegadores, armazena em cache todos os arquivos necessários para que funcione offline!</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/8243/demo-screenshot.png" style="display: block; height: 410px; margin: 0px auto; width: 480px;"><br>
+ <br>
+ <br>
+ Você pode ver o <a href="https://github.com/mdn/sw-test/">código-fonte no GitHub</a>, e <a href="https://mdn.github.io/sw-test/">ver um exemplo vivo</a>. A parte que mencionaremos aqui é a promise (veja <a href="https://github.com/mdn/sw-test/blob/gh-pages/app.js#L22-L47">app.js linhas 22-47</a>), que é uma versão modificada do que você leu a respeito acima, em <a href="https://github.com/mdn/promises-test">Promises test demo</a>. É diferente das seguintes formas:</p>
+
+<ol>
+ <li>No original, passamos somente uma URL para uma image que queríamos carregar. Nesta versão, passamos um fragmento de um JSON contendo todos os dados de uma única imagem (veja como se parecem em <a href="https://github.com/mdn/sw-test/blob/gh-pages/image-list.js">image-list.js</a>). Isto porque todos os dados para cada resolução de promise precisam ser transmitidos com a promise, pois é assíncrona. Se você passou apenas a url, e depois tentou acessar os outros itens no JSON separadamente, quando o laço de repetição <code>for()</code> estivesse sendo iterado posteriormente, não funcionaria, pois a promise não se resolveria ao mesmo tempo que as iterações estão sendo feitas (isso é um processo síncrono).</li>
+ <li>Na verdade, resolvemos a promise como uma matriz, pois queremos tornar o blob da imagem carregada disponível para a função de resolução mais adiante no código, além do nome da imagem, créditos e texto alternativo (veja <a href="https://github.com/mdn/sw-test/blob/gh-pages/app.js#L31-L34">app.js linhas 31-34</a>). Promises resolverão somente com um único argumento, então, se você quiser resolver múltiplos valores, precisará usar uma matriz/objeto..</li>
+ <li>Para acessar os valores da promise resolvida, acessamos esta função como esperado (veja <a href="https://github.com/mdn/sw-test/blob/gh-pages/app.js#L60-L64">app.js linhas 60-64</a>). Pode parecer um pouco estranho no começo, mas é assim que as promises funcionam.</li>
+</ol>
+
+<h2 id="Inserir_service_workers">Inserir service workers</h2>
+
+<p>Agora vamos aos service workers!</p>
+
+<h3 id="Registrando_seu_worker">Registrando seu worker</h3>
+
+<p>O primeiro bloco de código do nosso arquivo do app JavaScript — <code>app.js</code> — é conforme segue. Este é nosso entry point para usar service workers.</p>
+
+<pre class="brush: js notranslate">if ('serviceWorker' in navigator) {
+ navigator.serviceWorker.register('/sw-test/sw.js', {scope: '/sw-test/'})
+  .then(function(reg) {
+ // registration worked
+ console.log('Registration succeeded. Scope is ' + reg.scope);
+ }).catch(function(error) {
+ // registration failed
+ console.log('Registration failed with ' + error);
+ });
+}</pre>
+
+<ol>
+ <li>The outer block performs a feature detection test to make sure service workers are supported before trying to register one.</li>
+ <li>Next, we use the {{domxref("ServiceWorkerContainer.register()") }} function to register the service worker for this site, which is just a JavaScript file residing inside our app (note this is the file's URL relative to the origin, not the JS file that references it.)</li>
+ <li>The <code>scope</code> parameter is optional, and can be used to specify the subset of your content that you want the service worker to control. In this case, we have specified '<code>/sw-test/'</code>, which means all content under the app's origin. If you leave it out, it will default to this value anyway, but we specified it here for illustration purposes.</li>
+ <li>The <code>.then()</code> promise function is used to chain a success case onto our promise structure.  When the promise resolves successfully, the code inside it executes.</li>
+ <li>Finally, we chain a <code>.catch()</code> function onto the end that will run if the promise is rejected.</li>
+</ol>
+
+<p>This registers a service worker, which runs in a worker context, and therefore has no DOM access. You then run code in the service worker outside of your normal pages to control their loading.<br>
+ <br>
+ A single service worker can control many pages. Each time a page within your scope is loaded, the service worker is installed against that page and operates on it. Bear in mind therefore that you need to be careful with global variables in the service worker script: each page doesn’t get its own unique worker.</p>
+
+<div class="note">
+<p><strong>Note</strong>: Your service worker functions like a proxy server, allowing you to modify requests and responses, replace them with items from its own cache, and more.</p>
+</div>
+
+<div class="note">
+<p><strong>Note</strong>: One great thing about service workers is that if you use feature detection like we’ve shown above, browsers that don’t support service workers can just use your app online in the normal expected fashion. Furthermore, if you use AppCache and SW on a page, browsers that don’t support SW but do support AppCache will use that, and browsers that support both will ignore the AppCache and let SW take over.</p>
+</div>
+
+<h4 id="Why_is_my_service_worker_failing_to_register">Why is my service worker failing to register?</h4>
+
+<p>This could be for the following reasons:</p>
+
+<ol>
+ <li>You are not running your application through HTTPS.</li>
+ <li>The path to your service worker file is not written correctly — it needs to be written relative to the origin, not your app’s root directory. In our example, the worker is at <code>https://mdn.github.io/sw-test/sw.js</code>, and the app’s root is <code>https://mdn.github.io/sw-test/</code>. But the path needs to be written as <code>/sw-test/sw.js</code>, not <code>/sw.js</code>.</li>
+ <li>The service worker being pointed to is on a different origin to that of your app. This is also not allowed.</li>
+</ol>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/12630/important-notes.png" style="display: block; height: 277px; margin: 0px auto; width: 574px;"></p>
+
+<p>Also note:</p>
+
+<ul>
+ <li>The service worker will only catch requests from clients under the service worker's scope.</li>
+ <li>The max scope for a service worker is the location of the worker.</li>
+ <li>If your server worker is active on a client being served with the <code>Service-Worker-Allowed</code> header, you can specify a list of max scopes for that worker.</li>
+ <li>In Firefox, Service Worker APIs are hidden and cannot be used when the user is in <a href="https://support.mozilla.org/en-US/kb/private-browsing-use-firefox-without-history">private browsing mode</a>.</li>
+</ul>
+
+<h3 id="Install_and_activate_populating_your_cache">Install and activate: populating your cache</h3>
+
+<p>After your service worker is registered, the browser will attempt to install then activate the service worker for your page/site.<br>
+ <br>
+ The install event is fired when an install is successfully completed. The install event is generally used to populate your browser’s offline caching capabilities with the assets you need to run your app offline. To do this, we use Service Worker’s brand new storage API — {{domxref("cache")}} — a global on the service worker that allows us to store assets delivered by responses, and keyed by their requests. This API works in a similar way to the browser’s standard cache, but it is specific to your domain. It persists until you tell it not to — again, you have full control.</p>
+
+<div class="note">
+<p><strong>Note</strong>: The Cache API is not supported in every browser. (See the {{anch("Browser support")}} section for more information.) If you want to use this now, you could consider using a polyfill like the one available in <a href="https://github.com/Polymer/topeka/blob/master/sw.js">Google's Topeka demo</a>, or perhaps store your assets in <a href="/en-US/docs/Web/API/IndexedDB_API">IndexedDB</a>.</p>
+</div>
+
+<p>Let’s start this section by looking at a code sample — this is the <a href="https://github.com/mdn/sw-test/blob/gh-pages/sw.js#L1-L18">first block you’ll find in our service worker</a>:</p>
+
+<pre class="brush: js notranslate">this.addEventListener('install', function(event) {
+  event.waitUntil(
+    caches.open('v1').then(function(cache) {
+      return cache.addAll([
+        '/sw-test/',
+        '/sw-test/index.html',
+        '/sw-test/style.css',
+        '/sw-test/app.js',
+        '/sw-test/image-list.js',
+        '/sw-test/star-wars-logo.jpg',
+        '/sw-test/gallery/',
+        '/sw-test/gallery/bountyHunters.jpg',
+        '/sw-test/gallery/myLittleVader.jpg',
+        '/sw-test/gallery/snowTroopers.jpg'
+      ]);
+    })
+  );
+});</pre>
+
+<ol>
+ <li>Here we add an <code>install</code> event listener to the service worker (hence <code>this</code>), and then chain a {{domxref("ExtendableEvent.waitUntil()") }} method onto the event — this ensures that the service worker will not install until the code inside <code>waitUntil()</code> has successfully occurred.</li>
+ <li>Inside <code>waitUntil()</code> we use the <a href="/en-US/docs/Web/API/CacheStorage/open"><code>caches.open()</code></a> method to create a new cache called <code>v1</code>, which will be version 1 of our site resources cache. This returns a promise for a created cache; once resolved, we then call a function that calls <code>addAll()</code> on the created cache, which for its parameter takes an array of origin-relative URLs to all the resources you want to cache.</li>
+ <li>If the promise is rejected, the install fails, and the worker won’t do anything. This is ok, as you can fix your code and then try again the next time registration occurs.</li>
+ <li>After a successful installation, the service worker activates. This doesn’t have much of a distinct use the first time your service worker is installed/activated, but it means more when the service worker is updated (see the {{anch("Updating your service worker") }} section later on.)</li>
+</ol>
+
+<div class="note">
+<p><strong>Note</strong>: <a href="/en-US/docs/Web/Guide/API/DOM/Storage">localStorage</a> works in a similar way to service worker cache, but it is synchronous, so not allowed in service workers.</p>
+</div>
+
+<div class="note">
+<p><strong>Note</strong>: <a href="/en-US/docs/Web/API/IndexedDB_API">IndexedDB</a> can be used inside a service worker for data storage if you require it.</p>
+</div>
+
+<h3 id="Custom_responses_to_requests">Custom responses to requests</h3>
+
+<p>Now you’ve got your site assets cached, you need to tell service workers to do something with the cached content. This is easily done with the <code>fetch</code> event.</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/12634/sw-fetch.png" style="display: block; margin: 0 auto;"></p>
+
+<p>A <code>fetch</code> event fires every time any resource controlled by a service worker is fetched, which includes the documents inside the specified scope, and any resources referenced in those documents (for example if <code>index.html</code> makes a cross origin request to embed an image, that still goes through its service worker.)</p>
+
+<p>You can attach a <code>fetch</code> event listener to the service worker, then call the <code>respondWith()</code> method on the event to hijack our HTTP responses and update them with your own magic.</p>
+
+<pre class="brush: js notranslate">this.addEventListener('fetch', function(event) {
+ event.respondWith(
+ // magic goes here
+ );
+});</pre>
+
+<p>We could start by simply responding with the resource whose url matches that of the network request, in each case:</p>
+
+<pre class="brush: js notranslate">this.addEventListener('fetch', function(event) {
+ event.respondWith(
+ caches.match(event.request)
+ );
+});</pre>
+
+<p><code>caches.match(event.request)</code> allows us to match each resource requested from the network with the equivalent resource available in the cache, if there is a matching one available. The matching is done via url and vary headers, just like with normal HTTP requests.</p>
+
+<p>Let’s look at a few other options we have when defining our magic (see our <a href="/en-US/docs/Web/API/Fetch_API">Fetch API documentation</a> for more information about {{domxref("Request")}} and {{domxref("Response")}} objects.)</p>
+
+<ol>
+ <li>
+ <p>The <code>{{domxref("Response.Response","Response()")}}</code> constructor allows you to create a custom response. In this case, we are just returning a simple text string:</p>
+
+ <pre class="brush: js notranslate">new Response('Hello from your friendly neighbourhood service worker!');</pre>
+ </li>
+ <li>
+ <p>This more complex <code>Response</code> below shows that you can optionally pass a set of headers in with your response, emulating standard HTTP response headers. Here we are just telling the browser what the content type of our synthetic response is:</p>
+
+ <pre class="brush: js notranslate">new Response('&lt;p&gt;Hello from your friendly neighbourhood service worker!&lt;/p&gt;', {
+ headers: { 'Content-Type': 'text/html' }
+});</pre>
+ </li>
+ <li>
+ <p>If a match wasn’t found in the cache, you could tell the browser to simply {{domxref("GlobalFetch.fetch","fetch")}} the default network request for that resource, to get the new resource from the network if it is available:</p>
+
+ <pre class="brush: js notranslate">fetch(event.request);</pre>
+ </li>
+ <li>
+ <p>If a match wasn’t found in the cache, and the network isn’t available, you could just match the request with some kind of default fallback page as a response using {{domxref("CacheStorage.match","match()")}}, like this:</p>
+
+ <pre class="brush: js notranslate">caches.match('/fallback.html');</pre>
+ </li>
+ <li>
+ <p>You can retrieve a lot of information about each request by calling parameters of the {{domxref("Request")}} object returned by the {{domxref("FetchEvent")}}:</p>
+
+ <pre class="brush: js notranslate">event.request.url
+event.request.method
+event.request.headers
+event.request.body</pre>
+ </li>
+</ol>
+
+<h2 id="Recovering_failed_requests">Recovering failed requests</h2>
+
+<p>So <code>caches.match(event.request)</code> is great when there is a match in the service worker cache, but what about cases when there isn’t a match? If we didn’t provide any kind of failure handling, our promise would reject and we would just come up against a network error when a match isn’t found.</p>
+
+<p>Fortunately service workers’ promise-based structure makes it trivial to provide further options towards success. We could do this:</p>
+
+<pre class="brush: js notranslate">this.addEventListener('fetch', function(event) {
+ event.respondWith(
+ caches.match(event.request).then(function(response) {
+ return response || fetch(event.request);
+ })
+ );
+});</pre>
+
+<p>If the resources isn't in the cache, it is requested from the network.</p>
+
+<p>If we were being really clever, we would not only request the resource from the network; we would also save it into the cache so that later requests for that resource could be retrieved offline too! This would mean that if extra images were added to the Star Wars gallery, our app could automatically grab them and cache them. The following would do the trick:</p>
+
+<pre class="brush: js notranslate">this.addEventListener('fetch', function(event) {
+ event.respondWith(
+ caches.match(event.request).then(function(resp) {
+ return resp || fetch(event.request).then(function(response) {
+ return caches.open('v1').then(function(cache) {
+ cache.put(event.request, response.clone());
+ return response;
+ });
+ });
+ })
+ );
+});</pre>
+
+<p>Here we return the default network request with <code>return fetch(event.request)</code>, which returns a promise. When this promise is resolved, we respond by running a function that grabs our cache using <code>caches.open('v1')</code>; this also returns a promise. When that promise resolves, <code>cache.put()</code> is used to add the resource to the cache. The resource is grabbed from <code>event.request</code>, and the response is then cloned with <code>response.clone()</code> and added to the cache. The clone is put in the cache, and the original response is returned to the browser to be given to the page that called it.</p>
+
+<p>Cloning the response is necessary because request and response streams can only be read once.  In order to return the response to the browser and put it in the cache we have to clone it. So the original gets returned to the browser and the clone gets sent to the cache.  They are each read once.</p>
+
+<p>The only trouble we have now is that if the request doesn’t match anything in the cache, and the network is not available, our request will still fail. Let’s provide a default fallback so that whatever happens, the user will at least get something:</p>
+
+<pre class="brush: js notranslate">this.addEventListener('fetch', function(event) {
+ event.respondWith(
+ caches.match(event.request).then(function(resp) {
+ return resp || fetch(event.request).then(function(response) {
+ caches.open('v1').then(function(cache) {
+ cache.put(event.request, response.clone());
+ });
+ return response;
+ });
+ }).catch(function() {
+    return caches.match('/sw-test/gallery/myLittleVader.jpg');
+  })
+ );
+});</pre>
+
+<p>We have opted for this fallback image because the only updates that are likely to fail are new images, as everything else is depended on for installation in the <code>install</code> event listener we saw earlier.</p>
+
+<h2 id="Updating_your_service_worker"><a id="Updating your service worker" name="Updating your service worker">Updating your service worker</a></h2>
+
+<p>If your service worker has previously been installed, but then a new version of the worker is available on refresh or page load, the new version is installed in the background, but not yet activated. It is only activated when there are no longer any pages loaded that are still using the old service worker. As soon as there are no more such pages still loaded, the new service worker activates.</p>
+
+<p>You’ll want to update your <code>install</code> event listener in the new service worker to something like this (notice the new version number):</p>
+
+<pre class="brush: js notranslate">this.addEventListener('install', function(event) {
+ event.waitUntil(
+ caches.open('v2').then(function(cache) {
+ return cache.addAll([
+ '/sw-test/',
+ '/sw-test/index.html',
+ '/sw-test/style.css',
+ '/sw-test/app.js',
+ '/sw-test/image-list.js',
+
+ …
+
+ // include other new resources for the new version...
+ ]);
+ })
+ );
+});</pre>
+
+<p>While this happens, the previous version is still responsible for fetches. The new version is installing in the background. We are calling the new cache <code>v2</code>, so the previous <code>v1</code> cache isn't disturbed.</p>
+
+<p>When no pages are using the current version, the new worker activates and becomes responsible for fetches.</p>
+
+<h3 id="Deleting_old_caches">Deleting old caches</h3>
+
+<p>You also get an <code>activate</code> event. This is a generally used to do stuff that would have broken the previous version while it was still running, for example getting rid of old caches. This is also useful for removing data that is no longer needed to avoid filling up too much disk space — each browser has a hard limit on the amount of cache storage that a given service worker can use. The browser does its best to manage disk space, but it may delete the Cache storage for an origin.  The browser will generally delete all of the data for an origin or none of the data for an origin.</p>
+
+<p>Promises passed into <code>waitUntil()</code> will block other events until completion, so you can rest assured that your clean-up operation will have completed by the time you get your first <code>fetch</code> event on the new cache.</p>
+
+<pre class="brush: js notranslate">this.addEventListener('activate', function(event) {
+ var cacheWhitelist = ['v2'];
+
+ event.waitUntil(
+ caches.keys().then(function(keyList) {
+ return Promise.all(keyList.map(function(key) {
+ if (cacheWhitelist.indexOf(key) === -1) {
+ return caches.delete(key);
+ }
+ }));
+ })
+ );
+});</pre>
+
+<h2 id="Developer_tools">Developer tools</h2>
+
+<p>Chrome has <code>chrome://inspect/#service-workers</code>, which shows current service worker activity and storage on a device, and <code>chrome://serviceworker-internals</code>, which shows more detail and allows you to start/stop/debug the worker process. In the future they will have throttling/offline modes to simulate bad or non-existent connections, which will be a really good thing.</p>
+
+<p>Firefox has also started to implement some useful tools related to service workers:</p>
+
+<ul>
+ <li>You can navigate to <code><a href="/en-US/docs/Tools/about:debugging">about:debugging</a></code> to see what SWs are registered and update/remove them.</li>
+ <li>When testing you can get around the HTTPS restriction by checking the "Enable Service Workers over HTTP (when toolbox is open)" option in the <a href="/en-US/docs/Tools/Settings">Firefox Developer Tools settings</a>.</li>
+</ul>
+
+<div class="note">
+<p><strong>Note</strong>: You may serve your app from <code>http://localhost</code> (e.g. using <code>me@localhost:/my/app$ <strong>python -m SimpleHTTPServer</strong></code>) for local development. See <a href="https://www.w3.org/TR/service-workers/#security-considerations">Security considerations</a></p>
+</div>
+
+<h2 id="Specifications">Specifications</h2>
+
+<table class="standard-table">
+ <tbody>
+ <tr>
+ <th scope="col">Specification</th>
+ <th scope="col">Status</th>
+ <th scope="col">Comment</th>
+ </tr>
+ <tr>
+ <td>{{SpecName('Service Workers', '')}}</td>
+ <td>{{Spec2('Service Workers')}}</td>
+ <td>Initial definition.</td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<div>{{CompatibilityTable}}</div>
+
+<div id="compat-desktop">
+<table class="compat-table">
+ <tbody>
+ <tr>
+ <th>Feature</th>
+ <th>Chrome</th>
+ <th>Firefox (Gecko)</th>
+ <th>Internet Explorer</th>
+ <th>Opera</th>
+ <th>Safari (WebKit)</th>
+ </tr>
+ <tr>
+ <td>Basic support</td>
+ <td>{{CompatChrome(40.0)}}</td>
+ <td>{{ CompatGeckoDesktop("33.0") }}<sup>[1]</sup></td>
+ <td>{{CompatNo}}</td>
+ <td>24</td>
+ <td>{{CompatNo}}</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+
+<div id="compat-mobile">
+<table class="compat-table">
+ <tbody>
+ <tr>
+ <th>Feature</th>
+ <th>Android</th>
+ <th>Chrome for Android</th>
+ <th>Firefox Mobile (Gecko)</th>
+ <th>Firefox OS</th>
+ <th>IE Phone</th>
+ <th>Opera Mobile</th>
+ <th>Safari Mobile</th>
+ </tr>
+ <tr>
+ <td>Basic support</td>
+ <td>{{CompatNo}}</td>
+ <td>{{CompatChrome(40.0)}}</td>
+ <td>{{ CompatVersionUnknown }}</td>
+ <td>{{ CompatVersionUnknown }}</td>
+ <td>{{CompatNo}}</td>
+ <td>{{ CompatVersionUnknown() }}</td>
+ <td>{{CompatNo}}</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+
+<p>[1] Service workers (and <a href="/en-US/docs/Web/API/Push_API">Push</a>) have been disabled in the <a href="https://www.mozilla.org/en-US/firefox/organizations/">Firefox 45 Extended Support Release</a> (ESR.)</p>
+
+<h2 id="See_also">See also</h2>
+
+<ul>
+ <li><a href="https://serviceworke.rs/">The Service Worker Cookbook</a></li>
+ <li><a href="https://jakearchibald.github.io/isserviceworkerready/">Is ServiceWorker ready?</a></li>
+ <li>Download the <a href="https://mdn.mozillademos.org/files/12638/sw101.png">Service Workers 101 cheatsheet</a>.</li>
+ <li><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promises</a></li>
+ <li><a href="/en-US/docs/Web/Guide/Performance/Using_web_workers">Using web workers</a></li>
+</ul>