Blog de engenharia web.dev no 1: como criamos o site e usamos componentes da Web

Esta é a primeira postagem no blog de engenharia do web.dev. Queremos compartilhar insights úteis sobre nosso trabalho nos próximos meses. Então, fique de olho nas postagens com a tag do blog de engenharia. Vamos falar sobre o processo de criação do nosso site estático e os métodos (opcional) o JavaScript por trás dos componentes da Web.

O web.dev oferece conteúdo sobre a criação de experiências modernas na Web e permite que você meça o desempenho do seu site. Talvez os usuários mais experientes tenham percebido que nossa página de medição é apenas uma interface para o Lighthouse, que também está disponível no DevTools do Chrome. Ao fazer login no web.dev, você pode executar auditorias regulares do Lighthouse no seu site para acompanhar as mudanças na pontuação ao longo do tempo. Voltarei à página Medir um pouco mais tarde, porque achamos que ela é bastante especial. 🎊

Introdução

Basicamente, web.dev é um site estático gerado a partir de uma coleção de arquivos Markdown. Escolhemos o uso do Eleventy por ser uma ferramenta extensível e refinada que facilita a transformação de Markdown em HTML.

Também usamos pacotes JavaScript modernos que veiculamos apenas em navegadores compatíveis com type="module", incluindo async e await. Também usamos recursos que são suportados por navegadores contínuos, mas não por uma minoria de versões mais antigas. Como nosso site é estático, o JavaScript não é obrigatório para ler nosso conteúdo.

Quando o processo de criação, que envolve a geração de HTML estático e o agrupamento do nosso JavaScript com o Rollup, estiver concluído, o web.dev poderá ser hospedado com um servidor estático simples para teste. O site é quase completamente estático, mas temos algumas necessidades especiais que ainda se beneficiam de um servidor Node.js personalizado. Isso inclui redirecionamentos para domínios inválidos, bem como código para analisar o idioma de preferência de um usuário e verificar um recurso de internacionalização futuro.

Geração estática

Cada página em web.dev é escrita em Markdown. Todas as páginas incluem caso, que descreve os metadados sobre cada postagem. Esses metadados são ingeridos no layout de cada página, criando cabeçalhos, tags e assim por diante. Veja um exemplo:

---
layout: post
title: What is network reliability and how do you measure it?
authors:
  - jeffposnick
date: 2018-11-05
description: |
  The modern web is enjoyed by a wide swath of people…
---

The modern web is enjoyed by a wide swath of [people](https://www.youtube.com/watch?v=dQw4w9WgXcQ), using a range of different devices and types of network connections.

Your creations can reach users all across the world...

Esse caso inicial nos permite definir propriedades arbitrárias como autores, data de publicação e tags. O Eleventy expõe o caso em destaque como dados em quase todos os plug-ins, modelos ou outros contextos em que gostaríamos de fazer algo inteligente. O objeto de dados também contém o que o Eleventy descreve como cascata de dados, ou seja, uma variedade de dados extraídos de cada página, do layout da página e dos dados encontrados na estrutura de pastas hierárquica.

Cada layout único descreve um tipo diferente de conteúdo e pode herdar outros layouts. No web.dev, usamos esse recurso para enquadrar corretamente tipos diferentes de conteúdo (como postagens e codelabs) e, ao mesmo tempo, compartilhar um layout HTML de nível superior.

Coleções

O Eleventy oferece uma forma programática de criar coleções arbitrárias de conteúdo. Com isso, conseguimos oferecer compatibilidade com paginação e gerar páginas virtuais (páginas que não têm um arquivo Markdown correspondente no disco) para autores de postagens. Por exemplo, construímos nossas páginas de autor usando um modelo com uma expressão para o link permanente (para que o modelo seja renderizado novamente para cada autor) e uma coleção de apoio.

Isso resulta, por exemplo, em uma página simples contendo todas as postagens do Addy.

Limitações

No momento, não é fácil usar o processo de build do Eleventy porque ele é declarativo, e não imperativo: você descreve o que quer, e não como quer. É difícil executar o Eleventy como parte de uma ferramenta de build maior, já que ele só pode ser invocado pela interface de linha de comando.

Criação de modelos

O web.dev usa o sistema de modelos Nunjucks, originalmente desenvolvido pelo Mozilla. Nunjucks tem os recursos de modelos típicos, como loops e condicionais, mas também nos permite definir códigos curtos que geram HTML adicional ou invocam outra lógica.

Como a maioria das equipes que cria sites de conteúdo estático, começamos pequeno e adicionamos códigos curtos ao longo do tempo (cerca de 20 até o momento). A maioria deles só gera mais HTML (incluindo nossos componentes da Web personalizados). Veja um exemplo:

{% Aside %}
See how Asides work in the web.dev codebase
{% endAside %}

Ele vai ficar assim:

Mas, na verdade, ele está criando um HTML como o seguinte:

<div class="aside color-state-info-text">
<p>See how Asides work in the web.dev codebase</p>
</div>

Fora do escopo desta postagem, o web.dev também usa códigos curtos como um tipo de linguagem de metaprogramação. Os códigos curtos aceitam argumentos, sendo que um deles é o conteúdo contido. Não é necessário que os códigos curtos retornem nada, para que eles possam ser usados para criar o estado ou acionar algum outro comportamento. 🤔💭

Criação dos roteiros

Como mencionado, como web.dev é um site estático, ele pode ser disponibilizado e usado sem JavaScript e por navegadores mais antigos que não são compatíveis com type="module" ou outro código moderno. Essa é uma parte muito importante da nossa abordagem para tornar o web.dev acessível a todos.

No entanto, nosso código para navegadores modernos consiste em duas partes principais:

  1. Código de inicialização, que inclui código para estado global, análise e roteamento de SPA
  2. Código e CSS para Web Components que aprimoram progressivamente o site

O código de inicialização é bastante direto: o web.dev pode carregar novas páginas como um aplicativo de página única (SPA). Por isso, instalamos um listener global que detecta cliques nos elementos <a href="..."> locais. O modelo de SPA nos ajuda a manter o estado global da sessão atual do usuário. Caso contrário, todo novo carregamento de página acionaria chamadas ao Firebase para acessar o estado de login de um usuário.

Também especificamos alguns pontos de entrada diferentes em nosso site com base no URL acessado e carregamos o correto usando import() dinâmico. Isso reduz o número de bytes que nossos usuários precisam para que o site seja aprimorado com código.

Componentes da Web

Os Web Components são elementos personalizados que encapsulam a funcionalidade do ambiente de execução fornecida em JavaScript e são identificados por nomes personalizados, como <web-codelab>. O design funciona bem com sites praticamente estáticos, como web.dev: o navegador gerencia o ciclo de vida de um elemento à medida que o HTML do site é atualizado, informando corretamente todos os elementos quando eles são anexados ou desconectados da página. E os navegadores antiquados simplesmente ignoram os componentes da Web e renderizam o que for deixado no DOM.

Cada componente da Web é uma classe com métodos, incluindo connectedCallback(), disconnectedCallback() e attributeChangedCallback(). Os elementos personalizados do web.dev herdam principalmente de LitElement, que fornece uma base simples para componentes complexos.

Embora o web.dev use componentes da Web em muitas páginas, ele não é mais necessário do que a página Medir. Dois elementos oferecem a maior parte da funcionalidade que você vê nesta página:

<web-url-chooser-container></web-url-chooser-container>
<web-lighthouse-scores-container></web-lighthouse-scores-container>

Esses elementos criam outros elementos que oferecem mais funcionalidade. É importante ressaltar que esses elementos são apenas parte do código-fonte normal do Markdown, e nossa equipe de conteúdo pode adicionar mais funcionalidades a qualquer página, não apenas ao nó "Avaliar".

Nossos componentes da Web costumam usar o modelo componente de contêiner, que ficou conhecido pelo React, embora esse modelo já tenha sido aprovado (links em inglês). Cada elemento -container se conecta ao nosso estado global (fornecido pelo unistore) e renderiza um elemento visual que, por sua vez, renderiza nós do DOM reais com estilo ou outra funcionalidade integrada.

Um diagrama que mostra a relação entre o estado global e os elementos HTML que o utilizam.
Estado global e um componente da Web

Nossos componentes da Web mais complexos existem para visualizar ações globais e estados. Por exemplo, o web.dev permite que você faça a auditoria do seu site favorito e saia da página Medir. Se você voltar, vai ver que a tarefa ainda está em andamento.

Nossos componentes simples melhoram apenas conteúdo estático ou criam visualizações incríveis. Por exemplo, cada gráfico de linhas é o próprio <web-sparkline-chart>, que não tem relação com o estado global.

Vamos conversar

A equipe de engenharia do web.dev (Rob, Ewa, Michael e Sam) vai fazer mais análises técnicas em breve.

Esperamos que vocês tenham algumas ideias para seus próprios projetos. Entre em contato conosco no Twitter se tiver perguntas ou solicitações de assunto para este blog!