Myapp estende férias


Estou certo de que haverá entre o público respeitado quem me entenderá. O fato é que, em toda a abundância de bibliotecas e estruturas populares para o front-end da web, eu pessoalmente não gosto de quase todas as alternativas. Em cada uma das opções, encontro desvantagens significativas que me impedem de usá-las com calma. Tudo sempre começa de uma maneira otimista: um conceito interessante, som, à primeira vista, raciocínio em pontos "para" ... Mas então, tudo, repetidas vezes, começa a se deparar com dependências redundantes, entidades supérfluas e tentativas de resolver problemas que os próprios desenvolvedores criaram. Somos oferecidos a aprender uma nova sintaxe, aceitar novas idéias, aprender várias chavões, instalar muitos pacotes "necessários". Ok, adoro tudo novo e adoro palavras inteligentes. Mas fico muito desanimado quando o que pode ser feito simplesmente, as pessoas começam a se complicar fracamente. Você provavelmente já leu as confissões daqueles que, como eu, desesperavam-se de procurar o bom senso em tudo isso e decidiram ir ao outro extremo - escrever tudo "em baunilha". Isso aconteceu comigo quando fiquei decepcionado com o projeto Polymer , criado com a participação ativa dos desenvolvedores do Google. No começo, gostei muito de tudo, o lema desse movimento era a frase “Use the platform!”, Que significava para mim: “você não deve fazer no código o que o próprio navegador fará com mais eficiência”. A equipe da Polymer fez muito para introduzir novos padrões e recursos no nível da plataforma, e muito obrigado a eles por isso. Mas quando esses objetivos foram alcançados , eles mesmos começaram a violar seus próprios princípios. E agora sua nova biblioteca ( LitElement ) já se recusa a trabalhar diretamente no navegador sem instalar um ambiente especial, porque o pessoal não segue os padrões ... continuo monitorando o desenvolvimento do LitElement e até vejo sinais óbvios de que essas pessoas perdidas estão voltando ao caminho certo, mas eu já já Não vou usá-lo, porque agora tenho algo melhor.

O que?


Holiday.js é uma biblioteca para quem precisa de tudo o que precisa e não precisa de nada extra. Feriado - porque trabalhar com ela para mim é um feriado. E também porque eu escrevi, principalmente em férias ou em férias. No entanto, este é um projeto muito sério, com a ajuda de uma série de aplicações complexas sendo desenvolvidas para a "empresa sangrenta", que as pessoas gostam de assustar os iniciantes na construção de bicicletas. Também escrevo todos os meus projetos pessoais no Holiday.js.

Tudo é baseado em um grupo de padrões Custom Elements e Shadow DOM , como você deve ter adivinhado, e se você já estiver familiarizado com eles, será muito fácil descobrir isso.

Um pouco sobre você
Eu tenho 40 anos Atualmente, sou desenvolvedor web líder e engenheiro de P&D em uma empresa holandesa especializada em soluções de integração da IBM. Nossos clientes são grandes empresas: petróleo, gás, navios-tanque, ferrovias - isso é tudo. A essência do meu trabalho é expandir os recursos padrão para sistemas corporativos grandes e lentos e melhorar a experiência do usuário ao trabalhar com eles. Por um lado, tenho tios em laços, por outro - um novo vento de liberdade no desenvolvimento da web moderna. Esta é uma combinação interessante, permite que você veja muitas coisas de um novo ângulo. E eu gosto disso. Antes, eu tentei o papel de uma startup, engenheiro de ux, diretor de arte de um pequeno estúdio de design e muitos outros, então minha "experiência" geral é como uma colcha de retalhos. Mas isso não significa que me relacione superficialmente, apenas encontrei em muitos tipos de atividades princípios de engenharia semelhantes que me interessam antes de tudo.

Qual é o objetivo?


Se eu mesmo li um artigo semelhante para não perder mais interesse, gostaria de ver um exemplo de código de componente. Aqui está:

import {HdElement} from '../../holiday/core/hd-element.js'; class MyComponent extends HdElement { constructor() { super(); this.state = { imageURL: 'images/photo.jpg', firstName: 'John', secondName: 'Snow', }; } } MyComponent.template = /*html*/ ` <style> :host { display: block; padding: 10px; background - color: #fff; color: #000; } </style> <img bind="src: imageURL" /> <div bind="textContent: firstName"></div> <div bind="textContent: secondName"></div> `; MyComponent.is = 'my-component'; 

Aqui vemos que o componente possui um certo estado e modelo com atributos estranhos dos elementos " bind ". Esses atributos são a principal mágica: eles permitem analisar o modelo e salvar uma cópia do resultado na memória para uso posterior (clonagem) SEM processamento adicional da sequência de modelos no tempo de execução JS, que oferece alto desempenho durante a renderização inicial quando cada componente é instanciado. Ao contrário de muitas bibliotecas modernas nas quais a parte do DOM pela qual o componente é responsável é determinada pela função do estado, no Holiday.js um modelo é um produto semi-acabado que define a estrutura inicial e possibilita a vinculação de dados posteriormente, usando a API DOM usual, e funciona muito rápido. Voltaremos à questão da velocidade.

Vou listar outras vantagens:

  • Proximidade máxima de APIs nativas, abstrações adicionais mínimas
  • Sintaxe de modelo nativa: você não precisa aprender novo HTML e CSS
  • Para começar, você não precisa instalar nada adicional; seu projeto pode não ter uma pasta node_modules
  • Facilidade: você não forçará os usuários a esperar muito tempo por downloads
  • O kit inclui gerenciamento de estado global, roteamento, uma biblioteca de interface do usuário: você não se sentirá no deserto

A documentação principal do projeto: https://holiday-js.web.app/

Ciclo de vida


Vejamos os estágios do ciclo de vida do componente:

 import {HdElement} from '../../holiday/core/hd-element.js'; class LifecycleExample extends HdElement { constructor() { super(); //   : this.state = { name: '', bigName: '', }; /*   ,      DOM  "   ",       .    ,      "defineAccessor": */ this.defineAccessor('name', (name) => { // Some accessor code: this.setStateProperty('name', name); }); /*    ,      DOM               . */ } connectedCallback() { super.connectedCallback(); /*  .    DOM.               . */ } stateUpdated(path) { /*        : */ if (path === 'name') { this.setStateProperty('bigName', this.state.name.toUpperCase()); } } attributeChangedCallback(attributeName, oldValue, newValue) { /*  .      . */ super.attributeChangedCallback(attributeName, oldValue, newValue); } disconnectedCallback() { /*  .    DOM.              */ } } LifecycleExample.template = /*html*/ ` <div bind="textContent: name"></div> <div bind="textContent: bigName"></div> `; /*  HTML-,     : */ LifecycleExample.logicAttributes = [ //   ,         'name', ]; /*     CustomElements: */ LifecycleExample.is = 'lifecycle-example'; 

Padrões


Como os modelos no Holiday.js são apenas literais de modelo padrão, você tem total liberdade em como colocá-los no projeto e em como formar seu conteúdo. Você pode colocá-los em módulos separados, pode defini-los juntamente com o código do componente ou pode gerá-los em tempo real a partir de dados. Você pode usar expressões e resultados de funções em modelos. Tudo isso oferece grandes oportunidades e liberdade de expressão. Por exemplo, você pode importar estilos comuns para um modelo, usar variáveis ​​e calcular valores em CSS sem usar pré-processadores e com grande conveniência, montar modelos a partir de peças prontas.

Uma parte importante dos modelos de componentes da web são os slots . Os slots permitem que você designe locais especiais no DOM "sombra" do seu componente, no qual seus descendentes diretos serão exibidos na árvore DOM geral. Um exemplo:

 <header> <slot name="header"></slot> </header> <div class="toolbar"> <slot name="toolbar"></slot> </div> <div class="content"> <slot></slot> </div> <footer> <slot name="footer"></slot> </footer> 

Colocação em slots:

 <my-component> <div slot="header">Header content</div> <toolbar-component slot="toolbar"></toolbar-component> <div>Content of the default slot...</div> <div slot="footer">Footer content...</div> </my-component> 

Como você deve ter adivinhado, isso permite criar layouts de componentes, onde os módulos desejados podem ser facilmente classificados em células.

Como mencionado acima, para vincular dados e manipuladores dinamicamente, o atributo "bind" é usado:

 <div bind="textContent: content; onclick: on.clicked"></div> 

Para vincular valores de atributo, use o símbolo "@" no início do nome da propriedade:

 <div bind="@style: style">Content...</div> 

Você pode encontrar mais detalhes na seção correspondente da documentação: https://holiday-js.web.app/?templates

Gestão estatal


Dentro do componente:

 class MyComponent extends HdElement { constructor() { super(); //        : this.state = { content: 'Initial Content', style: 'color: #f00', on: { clicked: () => { console.log('Clicked!'); }, }, }; //       "setStateProperty": window.setTimeout(() => { //   : this.setStateProperty('content', 'Updated Content'); //   : this.setStateProperty({ 'content': 'Updated Content', 'style': 'color: #00f', }); }, 1000); } } 

Para controlar o estado no nível de todo o aplicativo, o módulo HdState é usado.
Exemplo de uso:

 import {HdState} from '../../holiday/core/hd-state.js'; //   : HdState.subscribe('ui.loading', (val) => { console.log(val); }); //   : HdState.publish('ui.loading', true); // : HdState.publish({ 'ui.loading': true, 'ui.sidePanelActive': true, }); 

Para trabalhar com o estado global, primeiro você precisa determinar seu esquema geral:

 HdState.applyScheme({ ui: { loading: { /*      ,       : */ type: Boolean, //    : value: false, }, sidePanelActive: { type: Boolean, value: false, }, }, user: { authorized: { type: Boolean, value: false, }, name: { type: String, value: null, //          : cache: true, }, }, }); 

O circuito também pode ser convenientemente dividido em blocos lógicos separados.

Para evitar vazamentos de memória, assinaturas irrelevantes devem ser descartadas:

 let subscription = HdState.subscribe('ui.loading', (val) => { console.log(val); }); window.setTimeout(() => { // Unsubscribe: subscription.remove(); }, 10000); 

Documentação do estado: https://holiday-js.web.app/?state

Ferramentas de desenvolvimento


O menor conjunto para começar é um editor de texto e um navegador. Sim, basta tentar. Note-se que nesta configuração, o navegador deve ser exatamente o Firefox. Ele pode carregar módulos ES sem usar um servidor local.

Para um trabalho mais completo, você precisará do git e de qualquer servidor da web que você goste (para trabalhar com módulos ES em outros navegadores).

Para destacar a sintaxe HTML e o preenchimento automático em literais de modelo, eu uso a extensão para o VS Code, originalmente projetada para funcionar com lit-html: https://github.com/pushqrdx/vscode-inline-html

Para criar o código antes da publicação, você pode usar qualquer compilador popular, como webpack ou rollup .

Desempenho


Os benchmarks para estruturas não são fáceis de escrever. Para uma comparação representativa, você deve comparar coisas comparáveis ​​e, na medida do possível, minimizar os efeitos dos efeitos colaterais. Portanto, eles devem ter uma ideia clara do que está acontecendo "sob o capô" em cada caso. Primeiro, você precisa decidir quais parâmetros serão medidos. Para o nosso caso, é importante para nós:

  1. Hora de iniciar a execução do programa principal (download)
  2. Tempo de renderização inicial do componente
  3. Hora de atualizar esses componentes e redesenhá-los

Infelizmente, não temos uma maneira confiável de descobrir o momento em que o navegador executou o programa e terminou a renderização completamente. No nível do navegador, existem muitas de nossas próprias otimizações, que para nós são algo como uma "caixa preta" e podem diferir em diferentes mecanismos. O que podemos usar: API de desempenho , requestAnimationFrame e método requestIdleCallback não padrão, que funciona apenas no Chrome e Firefox. Chega pela primeira vez.

Com que compararemos o Holiday.js? Comecei com duas bibliotecas: React (onde sem ele) e LitElement (tecnologias similares no núcleo). Você pode encontrar o código de referência nestes repositórios:

https://github.com/foxeyes/holiday-benchmark
https://github.com/foxeyes/lit-benchmark
https://github.com/foxeyes/react-benchmark

Infelizmente, ainda não terminei o teste de automação, e isso também não é fácil, porque a automação não deve criar efeitos colaterais por si só. No momento, continuo trabalhando nessa questão e estou preparando uma ferramenta apropriada usando o Puppeteer (uma coisa muito útil, eu recomendo). Enquanto isso, você pode tentar os testes no modo manual (Chrome / Firefox) e verificar os resultados no console do navegador. Você verá que o Holiday.js é um líder confiante em todos os casos .

Você pode perceber que, no caso do React, um contêiner div adicional é criado quando os componentes são exibidos, o que serve para nivelar o número de elementos DOM criados. Decidi que isso seria verdade, porque um componente da web é sempre um elemento DOM e um contêiner, e a correspondência das estruturas da árvore DOM em diferentes testes é muito importante. Além disso, é possível se livrar do aninhamento desnecessário no Holiday.js e exibir os dados da mesma maneira que no React. No entanto, se esse problema lhe parecer controverso, preste atenção, antes de tudo, na velocidade das atualizações.

Suporte do navegador


Não, o Internet Explorer não é suportado. Isso poderia ter sido alcançado com certos esforços (para a 11ª versão), mas a rejeição do apoio é uma posição de princípio. Em primeiro lugar, acredito que o IE deve morrer por um longo tempo e em nosso poder contribuir para isso. Em segundo lugar, as pessoas que defendem o suporte ao IE geralmente cometem um sério erro lógico: a participação do IE no tráfego total, de acordo com os dados atuais de caniuse, é de ~ 1,6% para todas as versões encontradas. E o navegador mais popular, que ultrapassa o resto por uma ampla margem, é o Chrome para dispositivos móveis (~ 35%). Portanto, apoiando o IE, você se recusa conscientemente a usar um grande número de tecnologias que são simplesmente necessárias para implementar total adaptabilidade e mobilidade em seus aplicativos, ou seja, por uma pequena minoria, complicam a vida da grande maioria de seus usuários. Ou aumente significativamente o custo de desenvolvimento e manutenção de seus produtos. Em terceiro lugar, a Microsoft, nos últimos tempos, tem forçado ativamente os usuários a abandonar o Windows 7, para que a proporção do tráfego do IE em um futuro próximo diminua mais rapidamente. Admito que há casos em que o suporte ao IE não pode ser ignorado, mas esses casos são muito mais raros do que costumávamos pensar.

Em 15 de janeiro deste ano, a Microsoft lançou uma versão de lançamento do novo Edge , no mecanismo Chromium. A partir deste momento, podemos assumir que o Holiday.js é suportado nativamente em todas as versões atuais de navegadores populares. Para o Edge mais antigo, é necessário um polyfill . A capacidade de trabalhar com polyfills é implementada no Holiday.js, mas o próprio script precisa ser conectado separadamente.

Minimalismo


O conceito de Holiday.js é baseado na simplicidade e no minimalismo. Uma das etapas importantes do trabalho neste projeto para mim foi a remoção da funcionalidade , que me apressei em implementar, mas depois percebi que poderia passar sem ela. Portanto, se lhe parece que algo realmente está faltando, faça uma pergunta a si mesmo, será mesmo? Respondi por mim mesmo assim: se algo for necessário demais, é melhor criar uma classe estendida separadamente, com herança da classe principal. Até agora, essa abordagem não me falhou. O Holiday.js, em seu estado atual, foi testado em batalha e mostrou-se muito positivo no trabalho.

Planos


Se você ler sobre este lugar, meus esforços já foram gastos em vão. Mesmo se você não quiser usar o Holiday.js, poderá obter pelo menos algo interessante para trabalhar com componentes da Web como tal. Ficarei muito feliz se este material marcar o início da construção da comunidade. Ficarei muito feliz em ter uma discussão construtiva, críticas, relatórios de bugs, solicitações de pull e, é claro, estrelas no GitHub. É claro que não pude abordar todos os aspectos e ficarei feliz em responder às suas perguntas. Por favor, leve em consideração que, até agora, eu trabalhei nessa biblioteca sozinho e é difícil fazer tudo sozinho, incluindo documentação, testes e ferramentas relacionadas, paralelamente aos principais trabalhos e projetos de animais de estimação.

No entanto, em um futuro próximo:

  • Mais comparações com outras bibliotecas e estruturas populares.
  • Ferramenta de teste PingPong minimalista e flexível baseada em Puppeteer
  • Gerador básico de projeto com exemplos (Starter Kit)
  • Desenvolvimento adicional da documentação

Cruzo os dedos, pressiono "Publicar" ...

Source: https://habr.com/ru/post/pt485688/


All Articles