No investimento, existe o conceito de "Mau agora - bom então". O investidor regularmente consome 10, 20% ou até 30% de seus ganhos para o futuro. Ele investe esse dinheiro em títulos, ações, OFZs, ETFs - que vale muito a pena. Agora, no momento, o investidor está retirando seus ganhos, está se privando de alguns benefícios, para que, no futuro, no horizonte de 10 a 20 anos, ele se beneficie de investimentos. Os lucros no futuro cobrirão as dificuldades de hoje. Sobre a mesma estratégia professada por
Alexei Okhrimenko (
obenjiro ), mas com relação ao desenvolvimento - é melhor perder um dia e depois voar em 5 minutos.
FonteNo
Frontend Conf 2018, Alexey contou como, tendo perdido muito tempo agora, finalmente o salvou mais tarde. Este relatório não trata de um sentimento de tédio e não trata de como lidar com tarefas monótonas e rotineiras, mas de como
gastar o tempo ao máximo - quanto custa, gastar tudo e ver o que vem dele. A transcrição do relatório é a experiência de escrever ferramentas para depuração, teste, otimização, andaimes e validação para diferentes projetos. Como bônus, Alexey falará sobre várias ferramentas existentes e os benefícios que elas trazem. Vamos descobrir se você precisa perder tempo com isso.
Sobre o palestrante: Alexei Okhrimenko é desenvolvedor da Avito Frontend Architecture, onde melhora um pouco a vida de milhões de pessoas. Lidera o podcast
“5 min Angular” e, em seu tempo livre de sono e podcast, organiza o
Angular Meetup junto com os caras de Tinkoff e faz um grande número de
relatórios diferentes e
controversos .
Onde posso perder tempo?
O passo zero é comprar um Mac / iMac e imediatamente começar a perder tempo, ou colocar o Linux em um laptop e perder todo o tempo de trabalho nele, alterando as configurações. Eu também recomendo começar com o Gentoo.
Existem 8 pontos em que podemos gastar tempo.
- Terminal
- Design.
- Crie um projeto.
- Geração de código.
- Código de ortografia.
- Refatoração
- Teste.
- Depuração
Prosseguimos com uma perda sólida começando em ordem.
Terminal
Onde no terminal podemos gastar nosso tempo para perder tudo?
Organize sua área de trabalho - crie pastas "Meu trabalho", "Meus projetos de hobby" e coloque tudo nelas. Configure o
Homebrew para instalar software adicional que será mencionado.

Coloque o
iTerm2 e o terminal padrão no Mac - jogue-o fora.

Instale complementos como o
oh-my-zsh , que vem com vários plugins muito legais.

Entregue o
tmux - multiplexador de terminal. Este é um programa para o terminal, que permite abrir várias janelas em uma janela e dar suporte adicional à sessão. Normalmente, se você fechar o terminal, tudo será interrompido e o tmux continuará funcionando, mesmo que você o tenha desligado. Se nunca trabalhei com o tmux, recomendo uma
revisão do DBMS Studio .
Prescreva aliases . Toda vez que você escreveu algo mais de uma vez no terminal - escreva seu nome alternativo, será útil. Duas vezes - já muita, certamente haverá uma terceira, sexta e décima.

Entregue ferramentas adicionais, por exemplo,
jmespath ou de
forma abreviada - jp. Ele pode ser instalado por meio do brew e fazer solicitações de consulta interessantes em arquivos JSON.
brew tap jmespath/jmespath brew instal jp
Por exemplo, você empacotou arquivos JSON, pode pesquisar tudo e descobrir quais versões do React em seus aplicativos e projetos.

Automatize seu trabalho - não abra os mesmos arquivos muitas vezes!
Agora vamos falar sobre onde gastar tudo. Tudo o que está acima é uma pequena perda de tempo, você pode perder mais nos Shell Scripts.
Script de shell
É uma linguagem de programação, principalmente para o bash, com sua própria sintaxe.
#!/bin/bash for dir in 'ls $YOUR_TOP_LEVEL_FOLDER'; do for subdir in 'Is $YOUR_TOP_LEVEL_FOLDER/$dir' do $(PLAY AS MUCH AS YOU WANT); done done
O idioma está cheio - algumas pessoas criam jogos e servidores da web, o que eu não recomendo. Eu recomendo todo o trabalho que levou algum tempo para gastá-lo novamente e escrevê-lo totalmente no arquivo. Porque Todos os desenvolvedores conhecidos que trabalham no setor há muito tempo simplesmente criam seu próprio repositório GitHub para configurações e colocam a configuração no seu multiplexador de terminal TMUX, Shell Scripts, para inicialização.

Por que gastar muito tempo com o que já foi feito uma vez? Então, quando você muda para outro trabalho, eles trocam o computador no trabalho, a placa-mãe queima e você passa um dia ou dois ou três novamente para configurar o
ambiente . Quando você possui esse repositório, a instalação e a instalação levam apenas 10 minutos.
Desenho
Geralmente, todo mundo fica muito inspirado ao mesmo tempo: “Sim, design! Diagramas UML! ”, Mas quando digo a palavra UML em voz alta, muitos programadores familiares percebem:
- Em 2018 ?! Qual é o seu problema? UML é uma relíquia terrível do passado. Por que você está desenterrando um cadáver? Largue a pá!Mas a UML é muito útil. Por exemplo, em uma reunião do Scrum, um desenvolvedor Java ouve os programadores de Python discutirem a arquitetura de recursos de back-end. Ele esfrega a cabeça com tristeza e percebe que não entende nada, mas simplesmente perde uma hora do seu tempo. Um desenvolvedor Java não pode interagir com programadores Python - ele não diz como escrever código, usar classes, mixins ou qualquer outra coisa. Ele simplesmente não está envolvido no assunto. Nossa empresa possui JavaScript, Python e Lua. No momento, 2/3 das pessoas estão entediadas: primeiro 2/3, depois outras. UML resolve esse problema.
UML é uma linguagem visual abstrata universal para o design do sistema, que permite ignorar os recursos das linguagens.
Vou dar dois dos meus exemplos favoritos.
Diagramas de sequência
Esses diagramas ajudam a mostrar o histórico da interação ao longo do tempo.

No eixo vertical Y, uma dependência temporal diminui: primeiro obtemos uma solicitação de autenticação, depois damos uma resposta e depois colocamos algo nos logs. No eixo horizontal X já existe uma interação direta entre os personagens - participantes de algum evento.
Pessoalmente, uso periodicamente
diagramas de sequência para descrever a autenticação de processos em aplicativos. Ao fazer isso, eu, um desenvolvedor de JS, encontro uma linguagem comum com o back-end de Python, Lua e Java. Todos nós nos entendemos e sabemos como o código funcionará como resultado e não nos preocupamos com a implementação específica deste ou daquele idioma.
Diagrama de classe
Esses gráficos também são muito úteis. JavaScript tem classes, qual é o sentido dos diagramas? Mas existe o TypeScript e, com ele, você pode obter interfaces, classes abstratas - uma representação completa da arquitetura final.

Um minuto de design economiza uma semana de codificação.
PlantUML
Eu uso a biblioteca Java
PlantUML . Com ele, você pode usar algum tipo de dsl complicado, no qual, por exemplo, indica que a List é herdada de AbstractList, Collection de AbstractCollection, além de interação, agregação, propriedades, interfaces e tudo mais.
@startuml abstract class AbstractList abstract AbstractCollection interface List interface Collection List <|— AbstractList Collection <|— AbstractCollection Collection <|— List AbstractCollection <|— AbstractList AbstractList <|— ArrayList class ArrayList { Object[ ] elementData size() } enum TimeUnit { DAYS
Como resultado, recebo o diagrama final.

Tudo isso funciona bem, existem plugins para o Visual Studio Code.
Há outra aplicação interessante.
StarUML
Desenhamos o diagrama mais simples: existe uma classe base da qual a classe de teste é herdada.

Em seguida, usamos
StarUML . Não é muito caro e pode exportar para Java. Não existe uma ferramenta que exporte diagramas UML para código TypeScript, mas podemos exportar apenas usando StarUML para código Java.

Jsweet
Em seguida, aplicamos o
JSweet - uma biblioteca que permite converter o código Java em código TypeScript ou JavaScript.

Código Java ...
import java.until.*; public class BaseClass { public BaseClass(){ } protected String baseAttribute; }
... usando JSweet convertido em código TypeScript:
class BaseClass { public constructor) { this.baseAttribute = null; } baseAttribute : string; } BaseClass["_class«] = «BaseClass»;
Há um parâmetro adicional
_class
- este é um recurso do Java, que pode ser excluído. Como resultado, obtivemos uma tabela pronta do código TypeScript a partir de diagramas - uma base na qual você pode trabalhar. Além disso, essa base é projetada e clara para todos.
Passar um tempo projetando UML definitivamente vale a pena.
Criação de projeto
Quem configura o Webpack todas as vezes e cria o webpack-config em um novo projeto - pessoal, o que há de errado com você ?! Está tudo bem? Você precisa de ajuda? Se você for mantido refém - escreva as coordenadas nos comentários, enviaremos um helicóptero de resgate.
A maneira mais fácil de evitar isso e não configurar o mesmo sempre é
criar um repositório comum no GitHub localmente ou aumentar o IC do GitLub, clonar esse repositório, entrar nele e excluir a pasta git.
git clone something cd something rm -rf .git
Agora temos um projeto de referência do qual estamos clonando. Com essa abordagem, você pode obter um
bootstrap muito barato.
Yeoman - preterido. Slush - descontinuado
Esse
Yeoman preterido é muito arrogante. Não é preterido, apenas cada vez menos usa-o, como o
Slush . Essas são duas ferramentas idênticas, mas com uma base diferente:
Yeoman é Grunt e geração de código. Slush é Galp e geração de código .
Apesar do fato de as ferramentas serem interessantes, agora outras são mais usadas.
CLI angular, Criar aplicativo de reação, Vue CLI
Quem trabalha com Angular - use a CLI Angular. Crie o React App - quem trabalha com o React. Vue CLI - fãs do Vue.JS.
A maioria já mudou para essas ferramentas. Um dos principais argumentos pelos quais vale a pena trabalhar com a CLI é a
uniformidade . Se você esqueceu de pegar seu projeto usando a CLI, você tem certeza de que a pessoa que vem depois de você conhecerá a estrutura do projeto: equipes, recursos, que você pode executar testes de ponta a ponta e de unidade. Essas ferramentas são muito boas.
Vale a pena gastar tempo em projetos de inicialização usando a CLI, em vez da Yeoman? Sim, não hesite.
Geração de código
Nós temos uma certa base de código. Normalmente, quando iniciamos um projeto, criamos o Roteamento primeiro e depois o Redux - como podemos passar sem ele? Cada estrutura possui uma ferramenta especializada para geração de código. Em Angular, isso é
CLI Schematics . O Vue CLI possui uma seção separada para gerar
plug -
ins do Vue CLI : você pode
gerar algum código para nossos projetos na seção de plug-ins.
CLI Redux
Quero focar na CLI do React e do Redux, porque, a partir da minha prática, são os programadores do React que são os menos engajados na geração de código e é difícil olhar para ele. Sempre que as pessoas criam os mesmos arquivos e reclamam que é difícil trabalhar com o Redux, você precisa criar um monte de tudo. Então, já existem ferramentas!
Essa é a
CLI do
Redux , que criará um arquivo dock para você, no qual haverá efeitos, redutores e as ações correspondentes, componentes "estúpidos" e componentes "inteligentes". Além disso, você pode gerar seus componentes ou base de código usando a CLI do Redux. O Redux CLI é instalado de forma simples, você pode criar um projeto usando-o ou inicializá-lo em um projeto pronto, por exemplo, criado usando o Aplicativo Criar Reação.
npm i redux-cli -g blueprint new <project name> blueprint init blueprint g dumb SimpleButton
Existe outra ferramenta universal que não depende da estrutura -
Plop .
Plop

Eu descobri sobre ele recentemente. O Plop faz o mesmo que o anterior: ao inicializar esta ferramenta, você pode criar todos os componentes básicos necessários. Indique em quais componentes seu aplicativo consiste e apenas os gere. Portanto, você não perde tempo criando a base de código principal. Tendo uma história e especificação do usuário, você pode gerar funcionalidades básicas, testes, estilos básicos -
economize uma enorme quantidade de trabalho .
Você precisará ajustar todas as ferramentas - eu periodicamente ajusto o React Blueprint, faço minha biblioteca de componentes, mas
dessa vez compensa .
Escrita de código
Haverá trivialidade.
Snippets de código
Os trechos de código permitem que você escreva um pequeno fragmento, uma palavra-chave e obtenha uma funcionalidade pronta. Por exemplo, você pode criar um componente Angular escrevendo
@Component
.

Para React e Vue, existem os mesmos trechos de código.
Há um problema com os trechos de código comuns. Quanto mais profissional o desenvolvedor, menos ele usa trechos de código - simplesmente porque ele já sabe como tudo está escrito e é preguiçoso demais para criá-los. Ele já se lembrava de como escrever esse componente.
Deixe-me lembrá-lo de que
nosso objetivo é gastar tempo sem fazer nada de útil. Portanto, sentamos e escrevemos trechos de código. Aqui você pode gastar uma quantidade infinitamente grande de tempo, e o objetivo será alcançado.
Pessoalmente, trechos foram úteis quando trabalhei com o
i-bem.js :
modules.define("button<i>«,</i> [«i-bem-dom»], function(provide, bemDom) { provide( bemDom.declBlock( this.name, { /* */ }, { /* */ } ) ); });
Não há nada complicado nessa declaração, mas a sintaxe não é Angular, nem Reage, nem Vue, e é muito difícil lembrar das primeiras cem vezes. Cento e primeiro é lembrado. Fiquei atormentado, passei muito tempo e comecei a criar esses componentes em massa simplesmente devido ao uso de trechos de código.
Para quem trabalha com o WebStorm, isso não é muito útil, simplesmente porque não possui um ecossistema tão grande de plug-ins e, basicamente, tudo é incluído inicialmente - esse é um
IDE completo .
Extensões VScode / Extensões VIM
A situação com os editores do
Visual Studio Code e
VIM é diferente. Para obter qualquer benefício deles, você precisa instalar plugins. Você pode passar vários dias para encontrar todos os bons plugins e instalá-los - existem muitos plugins!

Eu matei uma quantidade insana de tempo procurando por eles, o que eu recomendo a você. Você pode sentar por horas, olhar, olhar para eles, em belos gifs animados - um milagre! Escreva nos comentários se você quiser que eu compartilhe tudo o que tenho.
Existem ferramentas que destacam automaticamente a complexidade do código, quais testes passam e quais não, quando você pode ver o motivo da falha diretamente no código, qual código passou ou não, autocomplits, autoprefixes - tudo isso nos plugins.
Aqui você pode gastar muito tempo e alcançaremos nosso objetivo. Obviamente, os plugins não são um pouco relevantes para escrever código, mas imagine que eles nos ajudem a escrevê-lo.
Refatoração
Este é o meu tópico favorito! E tanto que tenho um relatório separado sobre refatoração:
“Refatoração - onde? Para onde? Quando? De onde Porque Por que e como? ” Eu digo em detalhes o que é e como trabalhar com ele.
Eu
te aviso
imediatamente ,
refatoração não é o que você costuma imaginar . Normalmente, isso significa: "Aprimorei a base de código e adicionei um novo recurso". Isso não é refatoração. Se você tem dissonância cognitiva no momento, veja o relatório e ele será aprovado.
AngularJS Grunt -> webpack
Sobre refatoração, quero contar uma história instrutiva. Tínhamos um projeto AngularJS muito antigo, que foi construído usando Grunt com concatenação banal. O projeto foi escrito durante a primeira e a segunda versões do Angular. Por conseguinte, tudo era muito simples lá: os arquivos foram concatenados, depois uglificados, e é isso. Em algum momento, percebemos que tínhamos que mudar para o Webpack. Temos uma enorme base de código herdada - como traduzi-la para o Webpack?
Fizemos algumas visitas interessantes. Primeiro, eles se voltaram para a biblioteca
lebab.io .
Lebab.io
Essa biblioteca permite converter o código do ES5 para o ES6 e muito bem. Ela pega a antiga base de código e a transforma em uma nova: insere importações, usa novas linhas, classes, conjuntos
let
e
const
corretamente - tudo faz por você. A este respeito, uma biblioteca muito boa.

Instalamos este plugin, executamos o código do arquivo no
Lebab.io . Depois disso, eles usaram os
modelos do Bigode e o código, que parecia diferente nos novos Angular 1.6 e 1.5 com uma abordagem de componentes. Com a ajuda dos frequentadores, retiramos as peças necessárias; com a ajuda do Bigode, renderizamos nosso modelo de uma maneira diferente e passamos por um ciclo por todos os nossos arquivos.
var object_to_render = {key: «value», ...}; fs.readFile(path_to_mustache_template, function (err, data) { if (err) throw err; var output = Mustache.render(data.toString(), object_to_render); fs.saveFileSync(path_to_mustache_template); }):
Como resultado, convertemos uma enorme quantidade de código legado em um formato moderno e conectamos rapidamente o Webpack. Para mim, pessoalmente, a história é muito instrutiva.
Jsfmt
Esta é uma ferramenta que permite formatar a base de código e pesquisá-la não com uma pesquisa regular, mas
semântica . Conectamos nossa biblioteca, sistema de arquivos, lemos o arquivo e queremos encontrar algo. Abaixo está um exemplo abstrato, atualmente estamos trabalhando com Angular.
var jsfmt = require('jsfmt'); var fs = require('fs'); var js = fs.readFileSync('component.js'); jsfmt.search(js,"R.Component(a, { dependencies : z })").map((matches, wildcards) => { console.log(wildcards.z); });
É assim que nossa solicitação se parece:
<b>R.Component</b> (a, { dependencies: z })
R/Component
é sua própria biblioteca
R
e algum
Component
.
Esta parte parece muito estranha:
R.Component<b> (<u>a</b></u>, { dependencies: <b><u>z</b></u> })
Isso não parece ser JavaScript válido - e é verdade. Inserimos letras minúsculas, como espaços reservados, e informamos ao
Jsfmt que não estamos interessados no que existe: um objeto ou uma matriz, uma string ou um valor booleano, nulo ou indefinido - isso não importa. É importante obtermos links para
a e
z , após o qual, quando percorrermos toda a base de código, encontraremos todas as variantes de
z . Por exemplo, podemos encontrar todas as dependências desse componente. Graças a isso, você pode fazer refatoração complexa.
Usando a ferramenta, eu pude refatorar uma enorme base de código com uma abordagem semântica usando árvores e análises.
Não era necessário escrever consultas complexas, regulares complexos ou analisar uma árvore de sintaxe - acabei de formar uma consulta e indiquei o que alterar.
Duas ferramentas adicionais
Na refatoração, há uma coisa simples que tenho a dizer. Se você quiser refatorar algo, no Código do Visual Studio, selecione o código e haverá dicas e opções de refatoração que estão lá. Por exemplo, um método de extração, um método embutido.

O WebStorm possui um menu de contexto que pode ser chamado usando uma combinação de chaves, dependendo da configuração e da base de código reformada.

Em geral, o WebStorm tem mais comandos, agora é mais desenvolvido que o Visual Studio Code.
Teste
Agora o mais interessante e inspirador :)
Selenium IDE
Primeiro uma pequena história. De alguma forma, os testadores vieram até mim e disseram:
- Escrevemos testes de ponta a ponta, queremos automatizá-los e temos um IDE Selenium.O Selenium IDE é apenas um plugin para o Firefox que registra suas ações em um navegador. Ele lembra todas as suas etapas - cliques, rolagens, entradas, transições e você pode perder essas etapas novamente. Mas isso não é tudo. Você pode exportar o que escreveu, por exemplo, em Java ou Python e executar testes de ponta a ponta automatizados usando o Selenium IDE.
Parece ótimo, mas, na realidade, o Selenium IDE por si só não funciona perfeitamente e, além disso, naquela época ainda tínhamos
ExtJs .
Extjs
Se você teve ExtJs - simpatize e abrace. O Selenium IDE sempre grava o seletor mais exclusivo. Em nossos elementos, isso é id. Mas os ExtJs para cada elemento geram um ID aleatório, não sei por quê. Esse problema com ExtJs vem com a versão zero.
ExtJS = <div id="random_6452"/>
Como resultado, nossos testadores abriram o aplicativo pela manhã, registraram tudo e,
sem recarregar a página , executaram-no periodicamente, tentando entender se o back-end, por exemplo, havia quebrado. Eles atualizaram o back-end, mas não tocaram no front-end. O principal era não clicar em atualizar, porque depois disso um novo ID foi gerado.
Imediatamente os testadores tiveram uma ideia brilhante. O Selenium IDE pode exportar seus registros para o formato HTML - podemos trabalhar com HTML, temos mecanismos de modelagem - vamos tentar fazer isso!
Extensão do Google Chrome
Criou rapidamente uma extensão do Google Chrome e encontrou imediatamente o método chique
elementFromPoint
.
document.elementFromPoint(x, y);
Trite gravar o movimento do mouse na janela e, em seguida, chamar elementFromPoint, quando o clique funcionou, encontrei as coordenadas do elemento em que clicamos. Além disso, era necessário criar um certo seletor, de alguma forma, para selecionar esse elemento especificamente. Id não pode ser usado - o que fazer?
Surgiu uma idéia - além disso, pendure um
ID de teste especial nos componentes. Um ID de teste abstrato foi criado para o componente, necessário apenas para testes.
data-test-id="ComponentTestId«
Foi gerado apenas em um ambiente de teste e fizemos a
select
de acordo com o atributo de dados. Mas isso nem sempre foi suficiente. Por exemplo, temos um componente, mas por dentro ainda existe uma
div
,
span
,
icon
, ícone na tag i. O que fazer sobre isso?
Para essa cauda, geramos
XPath
adicionalmente:
function createXPathFromElement(elm) { var allNodes = document.getElementsByTagName('*'); for (var segs = [ ]; elm && elm.nodeType = 1; elm = elm.parentNode) { if (elm.hasAttribute('class')) { segs.unshift(elm.localName.toLowerCase() + '[a)class = «' + elm.getAttribute('class') + ' »] '); } else { for (i = 1, sib = elm.previousSibling; sib; sib = sib.previousSibling) { if (sib.localName = elm.localName) i++; }; segs.unshift(elm.localName.toLowerCase() + '[' + i + ']'); }; }; return segs.length ? '/' + segs.join('/') : null; };
Como resultado, é formado um seletor XPath exclusivo, que consiste, em um caso bem-sucedido, no atributo de dados do seletor pelo atributo de dados com o nome do componente:
<b><u>.//*[@data-test-id='ComponentName']</b></u>/ul/li/div/p[2]
Se ainda havia algum tipo de estrutura complexa dentro do componente, todo o resto se destacava de acordo com o XPath estrito - sem id. Evitamos a identificação porque trabalhamos com ExtJs.
Esse XPath pode ser facilmente testado. Todos nós gravamos, exportamos de volta para o documento HTML, enviamos de volta para o Selenium IDE e o executamos.

Criamos a Extensão do Chrome, que simplesmente gerou o formato de registro Selenium IDE, mas à sua maneira, não da mesma forma que o Selenium IDE. Adicionamos muitas verificações inteligentes para rolagem giratória, carregamento bem-sucedido de aplicativos - adicionamos nuances adicionais que o Selenium IDE não leva em consideração. Graças a isso, temos testes de ponta a ponta totalmente automatizados.
A única coisa que os testadores fizeram depois disso foi abrir qualquer versão do aplicativo, clicar, fazer upload no IDE Selenium, verificar, salvar como um código Python, aproveitar o aumento de salário e bônus e dizer "obrigado" para mim.
Para testes de unidade, não posso agradar as pessoas das comunidades React e VueJS - desculpe! Não conheço ferramentas semelhantes para React e VueJS - talvez sejam. Só vou agradar aqueles com Angular.
Simontest
Há um
plug- in do
SimonTest no Visual Studio Code for Angular.

unit- — unit-. :
- - , - . , unit-.
— .
Depuração
80% , 80% .
, ? ?
Chrome DevTools
, - , , , .

Debugger ? - - , . Profiler, , Dumps, runtime, , , .
Tracing
—
: . runtime : , , — promise, setTimeout, setTimeout promise. .

Spy-js vs TraceGL
:
Spy-js TraceGL . , . Debugger : , — ? , , — .
, , — , . , deadlocks — deadlock , .
JS , . . deadlocks .
Spy-js WebStorm, , . spy-js. TraceGL Mozilla. , , Firefox -. TraceGL , , , . TraceGL Chrome , , .
, WebStorm, Spy-js. : Spy-js, , . WebStorm : TypeScript, CoffeeScript, . Spy-js, , , , . .
, , 5 , : , , , . — , , .
?
- .
- , - , , -.
- . .
- — , , ;
- , : .
- , , — , .
- — .
- , ! .
? «, »:
— ! : , 5 ! !— 2018 . Frontend Conf . ++. ? ! Frontend Conf ++ , : , , .
. ..