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. Nos próximos meses, vamos compartilhar insights úteis do nosso trabalho. Fique de olho nas postagens com a tag do blog de engenharia. Aqui, vamos abordar o processo de build do nosso site estático e o (opcional!) JavaScript por trás dos nossos componentes da Web.

O web.dev oferece conteúdo sobre como criar experiências modernas na Web e permite medir a performance do seu site. Os usuários experientes podem ter percebido que nossa página de medição é apenas uma interface do Lighthouse, que também está disponível no Chrome DevTools. Ao fazer login no web.dev, você pode realizar auditorias regulares do Lighthouse no seu site para conferir como a pontuação muda com o tempo. Vou revisitar a página "Medir" um pouco mais tarde, porque acho que ela é bastante especial. 🎊

Introdução

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

Também usamos pacotes modernos do JavaScript que são veiculados apenas para navegadores com suporte a type="module", que inclui async e await. Também usamos recursos que têm suporte de navegadores evergreen, mas não de uma minoria de versões mais antigas. Como somos um site estático, o JavaScript não é necessário para ler nosso conteúdo.

Depois que o processo de build, que envolve a geração de HTML estático e o agrupamento do JavaScript com o Rollup, é concluído, o web.dev pode ser hospedado com um servidor estático simples para testes. O site é quase totalmente estático, mas temos algumas necessidades especiais que ainda se beneficiam de um servidor personalizado do Node.js. Isso inclui redirecionamentos para domínios inválidos, bem como código para analisar o idioma preferido de um usuário para um recurso de internacionalização futuro.

Geração estática

Cada página no web.dev é escrita em Markdown. Todas as páginas incluem material de abertura, que descreve os metadados de cada postagem. Esses metadados são processados no layout de cada página, criando títulos, 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...

Com esse material, podemos definir propriedades arbitrárias, como autor, data de publicação e tags. O Eleventy expõe convenientemente o front matter 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 a cascata de dados, uma variedade de dados extraídos de cada página individual, do layout usado pela página e dos dados encontrados na estrutura hierárquica de pastas.

Cada layout único descreve um tipo diferente de conteúdo e pode herdar de outros layouts. No web.dev, usamos esse recurso para enquadrar corretamente diferentes tipos 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 maneira programática de criar coleções arbitrárias de conteúdo. Isso nos permitiu criar suporte para 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, criamos nossas páginas de autores usando um modelo que contém uma expressão para o permalink (para que o modelo seja renderizado novamente para cada autor) e uma coleção de suporte.

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

Limitações

No momento, não é possível se conectar facilmente ao 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, porque 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 pela Mozilla. O Nunjucks tem os recursos típicos de criação de modelos, como loops e condicionais, mas também permite definir shortcodes que geram mais HTML ou invocam outra lógica.

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

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

O resultado será parecido com este:

Mas ele está criando um HTML parecido com este:

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

Embora esteja fora do escopo desta postagem, o web.dev também usa códigos curtos como um tipo de linguagem de metaprogramação. Os Shortcodes aceitam argumentos, sendo que um deles é o conteúdo contido. Os códigos de acesso não precisam retornar nada, então eles podem ser usados para criar estados ou acionar outros comportamentos. 🤔💭

Roteiro

Como mencionado anteriormente, como o web.dev é um site estático, ele pode ser veiculado e usado sem JavaScript e por navegadores mais antigos que não oferecem suporte a type="module" ou a outros códigos modernos. 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, Google Analytics e roteamento de SPA
  2. Código e CSS para componentes da Web que melhoram progressivamente o site

O código de inicialização é bastante simples: 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 em elementos <a href="..."> locais. O modelo de SPA nos ajuda a manter o estado global sobre a sessão atual do usuário. Caso contrário, cada nova carga de página acionaria chamadas para o Firebase para acessar o estado de login de um usuário.

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

Componentes da Web

Os componentes da Web são elementos personalizados que encapsulam a funcionalidade de execução fornecida em JavaScript e são identificados por nomes personalizados, como <web-codelab>. O design se adapta bem a sites bastante estáticos, como o web.dev: seu navegador gerencia o ciclo de vida de um elemento à medida que o HTML de um site é atualizado, informando corretamente os elementos quando eles são anexados ou removidos da página. E os navegadores antigos simplesmente ignoram os componentes da Web e renderizam o que resta no DOM.

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

Embora o Web.dev use os Web Components em muitas páginas, eles são mais necessários na página Métricas. Dois elementos fornecem a maior parte da funcionalidade exibida 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 Markdown normal, e nossa equipe de conteúdo pode adicionar funcionalidades estendidas a qualquer página, não apenas ao nó da métrica.

Nossos componentes da Web geralmente usam o modelo de componente de contêiner, que ficou famoso pelo React, embora esse modelo agora esteja um pouco desatualizado. Cada elemento -container se conecta ao nosso estado global (fornecido pelo unistore) e renderiza um elemento visual, que por sua vez renderiza nós 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 usam.
Estado global e um componente da Web

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

Nossos componentes simples aprimoram o conteúdo estático ou criam visualizações incríveis (por exemplo, cada gráfico de linhas é um <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 publicar mais detalhes técnicos em breve.

Esperamos que o conteúdo sobre como fazemos as coisas tenha dado algumas ideias para seus próprios projetos. Entre em contato com a gente no Twitter se tiver dúvidas ou sugestões de temas para este blog.