1. Olá!
Neste laboratório, você vai pegar um aplicativo da Web e adicionar um Web Worker para compartilhar o estado entre duas janelas abertas. Este é o oitavo de uma série de codelabs complementares para o workshop de Progressive Web Apps. O codelab anterior foi Inclusões do service worker. Este é o último codelab da série.
O que você vai aprender
- Adicionar um worker compartilhado entre várias janelas abertas
- Use o Comlink para facilitar o trabalho com workers
O que você precisa saber
- JavaScript
O que é necessário
- Um navegador compatível com workers da Web compartilhados
2. Começar a configuração
Comece clonando ou fazendo o download do código inicial necessário para concluir este codelab:
Se você clonar o repositório, verifique se está na ramificação pwa06--working-with-workers
. O arquivo zip também contém o código dessa ramificação.
Essa base de código exige o Node.js 14 ou versões mais recentes. Quando o código estiver disponível, execute npm ci
na linha de comando da pasta do código para instalar todas as dependências necessárias. Em seguida, execute npm start
para iniciar o servidor de desenvolvimento do codelab.
O arquivo README.md
do código-fonte explica todos os arquivos distribuídos. Além disso, estes são os principais arquivos com que você vai trabalhar ao longo deste codelab:
Arquivos de chave
js/preview.js
: arquivo JavaScript da página de prévia.js/main.js
: arquivo JavaScript principal do aplicativo.
3. Escrever um trabalhador
No momento, a funcionalidade de prévia do web app mostra apenas o conteúdo mais recente ao carregar. O ideal seria mostrar uma prévia dinâmica enquanto o usuário digita. Isso exige a compilação de grandes quantidades de dados e o transporte deles entre duas janelas abertas diferentes. Por isso, não é algo que queremos fazer na linha de execução principal de nenhuma das janelas abertas. Em vez disso, vamos usar um service worker da Web compartilhado.
Para começar, crie um arquivo js/worker.js
com o seguinte código:
import { expose } from 'comlink';
import { marked } from 'marked';
class Compiler {
state = {
raw: '',
compiled: '',
};
subscribers = [];
async set(content) {
this.state = {
raw: content,
compiled: marked(content),
};
await Promise.all(this.subscribers.map((s) => s(this.state)));
}
subscribe(cb) {
this.subscribers.push(cb);
}
}
const compiler = new Compiler();
onconnect = (e) => expose(compiler, e.ports[0]);
Explicação
Esse código configura uma classe, chamada Compiler
, que permite definir conteúdo e chamar assinaturas depois que esse conteúdo é compilado. Como é um worker compartilhado, só pode haver uma única instância dessa classe em uso. Portanto, uma nova instância de Compiler
é instanciada. Em seguida, para que o trabalho com essa classe pareça perfeito de fora do worker, o Comlink é usado para expor a instância do compilador, permitindo que usemos todos os métodos como se ela tivesse sido declarada no código que a usa. Como esse é um worker compartilhado em vez de um worker dedicado, ele precisa ser exposto a todas as conexões.
4. Enviar conteúdo para o worker
Com o worker criado, agora precisamos enviar conteúdo para ele. Para isso, atualize js/main.js
para fazer o seguinte:
- Importe a exportação nomeada
wrap
decomlink
- Crie um novo Shared Worker com tipo de módulo chamado
worker
, defina o tipo comomodule
e aponte para ele usando o padrãonew URL
(new URL('./worker.js', import.meta.url)
). - Crie uma variável
compiler
quewrap
oworker.port
- Na função de atualização do editor (
editor.onUpdate
), depois de salvar o conteúdo no banco de dados, aguarde a conclusão decompiler.set
, transmitindo o conteúdo.
Explicação
Ao encapsular uma exportação do Comlink, é possível usar recursos como métodos de classe expostos como se eles não fossem compartilhados em um limite de worker. A exceção é que agora tudo é assíncrono. Como esse é um worker compartilhado em vez de um dedicado, o Comlink precisa encapsular a porta do worker em vez do próprio worker. Agora, sempre que uma atualização for feita no editor, o conteúdo será enviado ao worker para ser trabalhado.
5. Atualizar a página de visualização
A etapa final é extrair o conteúdo compilado do worker compartilhado para a prévia. A configuração para fazer isso é praticamente a mesma, mas como as funções não podem ser transmitidas entre o limite do worker, é necessário usar um proxy para a função. O Comlink está aqui para ajudar. Atualize js/preview.js
para fazer o seguinte:
- Importe as exportações nomeadas
wrap
eproxy
decomlink
. - Crie e encapsule o worker compartilhado como fez em
js/main.js
. - Chame o método
subscribe
do compilador com uma função de proxy que define a propriedadecompiled
dos dados recebidos como o HTML interno da área de visualização.
Depois disso, abra a prévia, comece a digitar no editor e se divirta e se anime ao ver seu Markdown ser compilado automaticamente e aparecer em tempo real na área de prévia, tudo sem bloquear a linha de execução principal de nenhuma das páginas.
6. Parabéns!
Você aprendeu a usar um worker compartilhado para compartilhar o estado entre várias instâncias de PWA.