Montamos um projeto conveniente da NPM para nós e para a equipe ou um pouco sobre as modernas ferramentas de front-end


Olá pessoal. Recentemente, deparei-me com a tarefa de configurar pacotes npm privados. Tudo parecia muito interessante e promissor, até que não havia muito o que fazer lá. Tudo teria terminado aqui, mas surgiu a segunda tarefa - escrever um repositório de demonstração para o pacote npm, que poderia ser usado, clonado e baseado nele rapidamente, criar algo útil e no mesmo estilo.


O resultado foi um projeto com formatação personalizada, estilo de código, testes para cada pool, limites de cobertura de código, relatório de cobertura de código e documentação automática. Além de publicação conveniente em npm. Detalhes sobre a configuração - sob o corte.


Exigências


Primeiro, descobri o que já temos:


  • Novos projetos são escritos em TypeScript
  • Além de novos projetos, há vários projetos em JavaScript puro
  • Existem requisitos para escrever testes e os resultados devem ser enviados para análise

Então ele estimou sua lista de desejos - já que há tempo e desejo, por que não ficar com calma? O que eu quero mais:


  • Eu quero um estilo de formatação uniforme
  • Quero um estilo TypeScript unificado
  • Quero documentação, mas não quero escrevê-la
  • Em geral, eu quero automatizar tudo ao máximo. O que fyr-fyr-fyr e em produção

Como resultado, os requisitos tomaram forma no seguinte:


  • O módulo deve ser TypeScript e testado usando TsLint
  • O módulo deve ser usado em TypeScript e em JavaScript
  • Os testes devem ser configurados no git hook, a cobertura mínima de código também deve ser configurada, as estatísticas devem ser
  • A formatação deve ser configurada
  • A documentação deve ser criada a partir do código.
  • A publicação deve ser conveniente e consistente.
  • Tudo isso pode ser automatizado

Parece ser bom, você precisa tentar.


Gestos preliminares


Criamos (clonamos) o repositório, inicializamos o package.json, configuramos o TypeScript localmente. Em geral, definimos todas as dependências localmente, porque tudo irá para o servidor. Não se esqueça de corrigir as dependências da versão .


git init npm init npm i -D typescript ./node_modules/.bin/tsc --init 

Imediatamente no local, você precisa ajustar o tsconfig.json por conta própria - defina target, libs, include / exclude, outDir e outras opções.


Estilo de formatação


Para manter a formatação uniforme, peguei duas ferramentas. O primeiro é o arquivo .editorconfig. Ele é entendido por todos os principais IDEs (WebStorm, VSCode, Visual Studio etc.), não requer instalação de nada supérfluo e funciona com um grande número de tipos de arquivos - js, ts, md e assim por diante.


 #root = true [*] indent_style = space end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true max_line_length = 100 indent_size = 4 [*.md] trim_trailing_whitespace = false 

Agora, o autoformato se comportará mais ou menos o mesmo com meus colegas.


A segunda ferramenta é mais bonita . Este é um pacote npm que verifica e, se possível, corrige automaticamente sua formatação de texto. Instale-o localmente e adicione o primeiro comando ao package.json


 npm i -D prettier 

package.json


 "prettier": "prettier --config .prettierrc.json --write src/**/*.ts" 

O Prettier não possui um comando init, portanto você precisa configurá- lo manualmente. Crie .prettierrc.json na raiz do projeto com algo parecido com este conteúdo controverso (se houver, a postagem não é sobre quais aspas são melhores, mas você pode tentar)


.prettierrc.json


 { "tabWidth": 4, "useTabs": false, "semi": true, "singleQuote": true, "trailingComma": "es5", "arrowParens": "always" } 

Agora crie a pasta src, crie index.ts com algum conteúdo condicional e tente executar mais bonita. Se ele não gostar da sua formatação, ele a corrigirá automaticamente. Muito confortável Se você não quiser se lembrar disso apenas durante uma confirmação / envio, poderá configurá-lo para executar automaticamente ou instalar uma extensão para o estúdio.


Estilo do código


Com o estilo do código, tudo também não é complicado. Para JavaScript, existe eslint ; para TypeScript, existe tslint . Colocamos tslint e criamos tsconfig.js para armazenar as configurações


 npm i -D tslint ./node_modules/.bin/tslint --init 

package.json


 "lint": "tslint -c tslint.json 'src/**/*.ts' 'tests/**/*.spec.ts'" 

Você pode escrever suas próprias regras ou pode usar regras existentes usando o parâmetro extend. Aqui , por exemplo, uma configuração do airbnb.


Desenvolvedores Tslint estão brincando
 module.exports = { extends: "./tslint-base.json", rules: { "no-excessive-commenting": [true, {maxComments: Math.random() * 10}] } }; 

Bem, isso não é bonito?


Há um ponto importante: tslint e mais bonitos se cruzam na funcionalidade (por exemplo, no comprimento de uma string ou vírgulas "penduradas"). Portanto, se você usar os dois, precisará monitorar a conformidade ou abandonar algo.


E, no entanto, para aqueles que desejam verificar nem todos os arquivos, mas apenas em etapas - existe um pacote em etapas


Testes


O que precisamos dos testes acima de tudo? Em primeiro lugar, para que iniciem automaticamente, em segundo lugar, controle de cobertura, em terceiro lugar algum relatório, de preferência no formato lcov (se houver, lcov é bem compreendido por diferentes analisadores - do SonarQube ao CodeCov). Lidaremos com a automação um pouco mais tarde, enquanto configuramos os próprios testes.


Colocamos karma , jasmim e todo o kit corporal correspondente


 npm i -D karma karma-jasmine jasmine karma-typescript karma-chrome-launcher @types/jasmine ./node_modules/.bin/karma init 

Modificamos um pouco o karma.conf.js e configuramos imediatamente o trabalho com cobertura


karma.conf.js
 karmaTypescriptConfig : { include: ["./src/**/*.ts", "./tests/**/*.spec.ts"], tsconfig: "./tsconfig.json", reports: { "html": "coverage", "lcovonly": { directory: './coverage', filename: '../lcov.dat' } }, coverageOptions: { threshold: { global: { statements: 60, branches: 60, functions: 60, lines: 60, excludes: [] }, file: { statements: 60, branches: 60, functions: 60, lines: 60, excludes: [], overrides: {} } } }, } 

E, é claro, não esqueça de adicionar um novo comando ao package.json


package.json


 "test": "karma start" 

Se você estiver usando ou planejando usar o IC, é melhor colocar o HeadlessChrome :


 npm i -D puppeteer 

E pré-configure o Karma (correção do Chrome no ChromeHeadless) e mais alguma coisa. As edições podem ser visualizadas no repositório de demonstração .


Execute os testes, verifique se tudo funciona. Ao mesmo tempo, verifique o relatório de cobertura (está na pasta de cobertura) e remova-o do controle de versão, pois não é necessário no repositório.


Relatório:



Estilo de confirmação


As confirmações também podem ser unificadas (e, ao mesmo tempo, levar alguém a ficar incandescente, se você exagerar, é melhor sem fanatismo). Por isso, assumi o compromisso . Ele funciona na forma de um diálogo, suporta o formato de registro de alterações convencional (você pode criar um registro de alterações a partir de suas confirmações) e existe um plug- in VsCode para ele


 npm i -D commitizen npm i -D cz-conventional-changelog 

cz-convencional-changelog é um adaptador responsável por perguntas e, como resultado, pelo formato de suas confirmações


Adicione um novo comando à seção de scripts


 "commit":"git-cz" 

E uma nova seção package.json - config for commitizen


 "config": { "commitizen": { "path": "./node_modules/cz-conventional-changelog" } } 

A caixa de diálogo com o commitizen fica assim:



A documentação


Agora para a documentação. Teremos dois tipos de documentação - do código e do commit. Para documentação do código, usei typedoc (análogo ao esdoc, mas para TypeScript). É muito simples de configurar e trabalhar. O principal é não se esqueça de remover os resultados de seu trabalho do controle de versão.


 npm i typedoc -D 

e atualize o package.json


package.json


 "doc": "typedoc --out docs/src/ --readme ./README.md" 

O sinalizador --readme forçará o leia-me a ser incluído na página principal da documentação, o que é conveniente.


O segundo tipo de documentação é o changelog, e o pacote changelog-cli convencional nos ajudará com isso.


 npm i -D conventional-changelog-cli 

package.json


 "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s" 

Do angular, há apenas formatação e nada mais. Agora, para atualizar o changelog, basta executar o npm run changelog. O principal é escrever cuidadosamente as confirmações. Bem, sempre escrevemos confirmações perfeitas, portanto isso não deve ser um problema.


Construir


Como nosso pacote também deve funcionar para JavaScript, precisamos transformar o TypeScript em JavaScript. Além disso, seria bom fazer um pacote compactado, apenas por precaução. Para isso, precisamos de uglifyjs e um pequeno pacote de ajustes.json


 npm i -D uglifyjs 

package.json


 "clean":"rmdir dist /S /Q", "build": "tsc --p ./ --sourceMap false", "bundle": "uglifyjs ./dist/*.js --compress --mangle --output ./dist/index.min.js" 

A propósito, se você deseja controlar o tamanho do seu projeto, existem mais dois pacotes interessantes



Eles também podem ser integrados no processo de confirmação / envio / publicação para permanecer no tamanho aceitável do pacote configurável. Muito, muito útil.


Automação


Bem, já tomamos as etapas básicas, agora tudo precisa ser automatizado; caso contrário, será francamente inconveniente para o trabalho.


Para isso, precisamos de mais um pacote - husky . Ele reescreve o git hooks e chama os comandos associados do package.json. Por exemplo, quando você confirma, o pré-comprometimento funciona, o push-push e assim por diante. Se o script retornar um erro, a confirmação falhará.


 npm i -D husky 

package.json


 "precommit":"npm run prettier", "prepush": "call npm run lint && call npm run test" 

Há uma nuance importante aqui, o uso da sintaxe de chamada não é multiplataforma e não decola em sistemas unix. Portanto, se você quiser fazer tudo honestamente, também precisará instalar o pacote npm-run-all , mas o mesmo será feito em várias plataformas.


Postagem


Bem, aqui chegamos à publicação do nosso pacote (embora vazio). Vamos pensar o que queremos da publicação?


  • Teste tudo de novo
  • Coletar artefatos de construção
  • Coletar documentação
  • Aumentar versão
  • Gatilho de tags
  • Enviar para npm

As mãos fazem tudo - triste. Ou você esquece alguma coisa ou precisa escrever uma lista de verificação. Também é necessário automatizar. Você pode colocar outro pacote - solte . E você pode usar os ganchos nativos do próprio npm - preversão, versão, pós-versão, por exemplo:


 "preversion": "npm run test", "version": "call npm run clean && call npm run build && npm run bundle && call npm run doc && call npm run changelog && git add . && git commit -m 'changelogupdate' --no-verify", "postversion": "git add . && git push && git push --tags", 

Resta especificar para package.json o que incluir no pacote, o ponto de entrada e o caminho para nossos tipos (não esqueça de especificar o sinalizador --declaration em tsconfig.json para obter os arquivos d.ts)


package.json


 "main": "./dist/index.min.js", "types": "./dist/index.d.ts", "files": [ "dist/", "src/", "tests/" ] 

Bem, isso parece ser tudo. Agora apenas faça


 npm version ... npm publish 

E tudo o mais será feito automaticamente.


Bônus


Como bônus, existe um repositório de demonstração que suporta tudo isso + CI usando travis-ci. Deixe-me lembrá-lo de que o HeadlessChrome está configurado lá; portanto, se isso for importante para você, recomendo que você procure lá.


Agradecimentos


Muito obrigado a Alexei Volkov por seu relatório sobre o JsFest, que se tornou a base deste artigo.


Graças ao max7z , indestrutível , justboris por esclarecer que os caminhos para as dependências locais podem ser omitidos.


E algumas estatísticas


  • Tamanho dos nós de módulo: 444 MB (NTFS)
  • Número de dependências do primeiro nível: 17
  • Total de pacotes usados: 643

Links úteis


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


All Articles