Yarn: Arquivos de bloqueio concorrentes criam UX pobre

Criado em 12 abr. 2018  ·  93Comentários  ·  Fonte: yarnpkg/yarn

NB: Estou criando esse problema no repositório do yarn, mas na verdade é um problema compartilhado entre o yarn e o npm.

Com o lançamento do npm 5 em maio, o ecossistema Node agora tem dois gerenciadores de pacotes baseados em lockfile. No geral, foi uma vitória para os usuários e foi bom ver a concorrência nesse espaço.

No entanto, agora que existem dois formatos de arquivo de bloqueio concorrentes, isso pode criar um novo problema para os usuários, especialmente os desenvolvedores iniciantes.

Quando o npm 5 foi lançado, o Heroku adicionava uma nova falha se um aplicativo fosse enviado com os arquivos npm e yarn lock . Nos últimos meses, este se tornou o motivo mais comum para a falha de builds do Node no Heroku e essas falhas representam cerca de 10-12% de todas as falhas de build do Node na plataforma. Milhares de desenvolvedores fazem isso todos os meses .

É surpreendentemente fácil terminar com ambos em seu repositório. Mesmo como um desenvolvedor experiente, descobri que estava executando a ferramenta errada para um projeto específico e tendo que me controlar antes de comprometer. Para um desenvolvedor inexperiente construindo seu primeiro projeto server / react / angular que pode não entender o que é um gerenciador de pacotes, lockfile ou git repo, isso pode ser altamente confuso.

Nenhuma ferramenta dará um aviso ou erro se o outro lockfile existir:

❯ ls *lock*   
ls: *lock*: No such file or directory

❯ npm --version
5.8.0

❯ yarn --version
1.5.1

❯ npm install
npm notice created a lockfile as package-lock.json. You should commit this file.

added 659 packages from 437 contributors in 10.553s

❯ yarn install  
yarn install v1.5.1
info No lockfile found.
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 📃  Building fresh packages...
success Saved lockfile.
✨  Done in 7.67s.

❯ ls *lock*          
package-lock.json yarn.lock

Isso provavelmente é especialmente verdadeiro para usuários do Yarn, onde a maior parte da documentação na web instrui os usuários a npm install . Os usuários que copiam e colam comandos de documentos ou Stack Overflow provavelmente vão parar aqui.

Falei com @zkat e @iarna no npm e @arcanis on yarn, e todos concordaram que esse é um problema que deve ser abordado, mas não houve acordo total sobre como. Idealmente, esta questão suscita discussão e ambas as ferramentas podem concordar sobre como podemos ajudar os usuários aqui.

Compilei uma lista de possíveis atenuações que me foram sugeridas:

Soluções potenciais

Fazer nada

Existe uma razão técnica para que um usuário queira dois arquivos de bloqueio? Nesse caso, como as ferramentas externas podem determinar qual gerenciador de pacotes deve ser usado para aquele aplicativo?

Erro se o outro arquivo de bloqueio existir

O Yarn poderia imprimir um erro e sair se package-lock.json existir e vice-versa.

Prós:

  • simples e fácil de implementar
  • o usuário recebe um erro quando está em posição de corrigi-lo imediatamente

Contras:

  • Não é uma experiência de usuário fantástica

Converta o outro arquivo de bloqueio

Yarn podia ler package-lock.json , convertê-lo em yarn.lock e remover package-lock.json . O npm poderia fazer o oposto.

Prós:

  • ótima experiência do usuário
  • os usuários que trocam de ferramentas não obteriam um novo conjunto de dependências como efeito colateral

Contras:

  • Meu entendimento é que, devido às diferentes estratégias de resolução de dependência, essa conversão teria perdas em ambos os sentidos
  • Requer que cada ferramenta adicione e mantenha o código para entender o outro arquivo de bloqueio
  • Os formatos de arquivos de bloqueio podem mudar com o tempo

Exclua o arquivo de bloqueio do outro

Basta remover o outro arquivo de bloqueio e criar um novo

Prós:

  • evita efetivamente esta situação

Contras:

  • comportamento surpreendente
  • o usuário obtém um novo conjunto de dependências

Execute a outra ferramenta para o usuário

Se o yarn vir um package-lock.json mas não um yarn.lock ele poderia registrar um aviso e chamar npm install para o usuário

Prós:

  • O usuário consegue o que quer

Contras:

  • Comportamento surpreendente
  • um pouco complicado

Adicione configuração a package.json para indicar

Adicione um campo em package.json para indicar qual gerenciador de pacotes um projeto deve usar

"package-manager": "yarn"

Prós:

  • Transmite explicitamente a intenção do usuário

Contras:

  • Adiciona mais configuração para o usuário

De outros?

Talvez eu esteja perdendo algo que funcionaria melhor

cat-compatibility needs-discussion triaged

Comentários muito úteis

Todos - Peço gentilmente que permaneçamos no assunto e deixemos qualquer comentário não diretamente relacionado off-line (por exemplo, nosso canal Discord). Há muitas pessoas inscritas neste tópico e, para ser justo, acho que a discussão sobre o fio npm <> não pertence aqui. Obrigado!

Todos 93 comentários

Adicione config a package.json para indicar

Pode ser um bom caso de uso para o campo engine 🤔

A viagem de ida e volta package-lock.jsonyarn.lockpackage-lock.json tem perdas, mas isso provavelmente não é importante. yarn.lockpackage-lock.jsonyarn.lock não deve causar perdas, AFAIK.

Do ponto de vista de npm , sou a favor da opção em que se yarn vê um package-lock.json e não um yarn.lock que importa e remove o package-lock.json . E da mesma forma, se npm vir um yarn.lock e nenhum package-lock.json ele deve fazer o mesmo, importando e removendo o `yarn.lock.

Isso permitiria aos usuários de ambas as ferramentas alternar perfeitamente sem deixar o projeto do usuário em um estado confuso (onde os arquivos parecem ser de ambos).

Estou um pouco preocupado com isso, porque significa que nem package-lock.json nem yarn.lock serão capazes de adicionar metadados aos arquivos (o Yarn não faz atualmente, mas por que não), removendo alguns liberdade para nossos formatos no processo.

Esse problema também levanta a questão da interoperabilidade entre o Yarn e o npm em geral, discutida originalmente em outro tópico - acho que tentar ser muito interoperável pode merecer nós dois, já que os usuários terão a expectativa de que tudo funcionará exatamente da mesma maneira em ambos os projetos, o que considero uma suposição perigosa (um exemplo óbvio é que os espaços de trabalho serão interrompidos silenciosamente se alguém executar o npm em um projeto com base em um espaço de trabalho).

@ yarnpkg / core, pensamentos?

Eu gosto da ideia de @iarna de fazer ambas as ferramentas migrarem de um arquivo de bloqueio para
outro na instalação automática.
Faz sentido excluir o arquivo de bloqueio importado após a migração para evitar
os dois gerenciadores de pacotes competem em um projeto.

Ambas as ferramentas podem imprimir avisos e talvez exigir a solicitação do usuário para prosseguir.

Também concordo com o ponto de Mael de que alcançar 100% de compatibilidade bloqueará
de explorar novos recursos, acho que devemos tratá-lo como um único
caminho de migração, que pode ser um recurso bastante pequeno em install.js em nosso
lado.

Na quarta-feira, 11 de abril de 2018 às 21h49, Maël Nison [email protected] escreveu:

Estou um pouco preocupado com isso, porque significa que nem
package-lock.json nem yarn.lock será capaz de adicionar metadados aos arquivos
(O Yarn atualmente não faz isso, mas por que não), removendo alguma liberdade para nossos formatos
no processo.

Este problema também levanta a questão da interoperabilidade entre Yarn e
npm em geral, discutido originalmente em outro tópico - estou com vontade de tentar
ser interoperável demais pode merecer nós dois, já que os usuários irão
tem a expectativa de que tudo funcionará exatamente da mesma maneira em ambos
projeto, que considero uma suposição perigosa (um exemplo óbvio é
que os espaços de trabalho serão interrompidos silenciosamente se alguém executar o npm em um
projeto movido a espaço de trabalho).

@ yarnpkg / core https://github.com/orgs/yarnpkg/teams/core , ideias?

-
Você está recebendo isso porque faz parte de uma equipe que foi mencionada.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/yarnpkg/yarn/issues/5654#issuecomment-380677110 ou mudo
o segmento
https://github.com/notifications/unsubscribe-auth/ACBdWI9jnLJeFqH8v2T-AB74sQO1PMIjks5tntzrgaJpZM4TQ5-B
.

Pingando @imsnif desde que ele expressou interesse em implementar a solução "Converter o outro arquivo de bloqueio" algumas semanas atrás. Ele pode até ter algum código funcionando agora.

Obrigado pelo ping!

Então, sim, estou trabalhando exatamente nisso. Eu estava planejando escrever um fio RFC e pingar todas as partes interessadas na próxima semana.

Resumidamente: fiz algum trabalho na conversão de yarn.lock <==> package-lock.json. Existem algumas perdas no processo, mas muito poucas delas são lógicas. A meu ver, isso é totalmente aceitável se estivermos falando sobre o cenário de 'conversão única' mencionado acima. Se quisermos discutir isso mais detalhadamente, posso entrar em mais detalhes.

Atualmente, tenho um código rudimentar que faz isso: https://github.com/imsnif/synp
Não é 100% e depende de uma pasta node_modules existente e atual para o projeto a ser convertido. Estou nos estágios finais de uma reescrita (no branch 2.0.0 ) que obterá o estado do pacote do registro (usando o incrível pacote lib).

O que eu quero fazer uma vez que estiver feito é começar a falar sobre como (e se?) Gostaríamos de implementar isso exatamente em yarn e npm .

Adoraria ouvir a opinião de todos sobre isso.

A meu ver, isso é totalmente aceitável se estivermos falando sobre o cenário de 'conversão única' mencionado acima

Eu não acho que será tão comum. Posso estar errado, mas acho que o caso de uso mais comum serão projetos usando Yarn, e um dos desenvolvedores copia / cola o comando de um README para adicionar uma dependência, usando npm vez de yarn no processo.

Neste contexto, ainda não estou convencido de que seja uma boa coisa perder dados e alterar o layout do pacote silenciosamente tentando fazer a coisa certa - eles provavelmente nem perceberão até que as coisas quebrem (poderíamos ter um prompt de confirmação, mas Estou esperando que as pessoas que copiam / colam esses comandos também confirmem cegamente os prompts de instalação). Pior, poderia funcionar na máquina deles, mas quebraria nos colegas quando eles voltassem para o Yarn.

@arcanis - Acho que todos os cenários e casos

Vejo esse recurso sendo usado principalmente em ambientes de CI, onde acho que pode brilhar (como o OP mencionou). No mínimo, porém, acho que ambas as ferramentas devem estar cientes do arquivo de bloqueio da outra ferramenta. Deixando as especificações de quando eles decidem fazer a conversão para eles. O que você acha?

Vejo esse recurso sendo usado principalmente em ambientes de CI, onde acho que pode brilhar (como o OP mencionou).

Você tem um exemplo? Supõe-se que os sistemas de CI atuem de uma maneira muito determinística, cometendo acidentalmente um lockfile convertido é algo que deveria ser detectado pior no momento PR, agora, CI é tarde demais para isso.

No mínimo, porém, acho que ambas as ferramentas devem estar cientes do arquivo de bloqueio da outra ferramenta.

Talvez. Usar a versão engine para forçar um gerenciador de pacotes específico parece mais limpo para mim, ambos os projetos teriam apenas que manter uma lista de motores exclusivos (como "yarn" não pode ser satisfeito em "npm", e inversamente).

Na minha opinião, converter os arquivos de bloqueio em tempo real também não é muito escalonável. Por exemplo, estivemos falando apenas sobre o arquivo package-lock.json até agora, mas acho que o pnpm tem seu próprio arquivo de bloqueio chamado shrinkwrap.yaml . Seria bom se pudéssemos encontrar uma maneira de lidar com os dois e qualquer outro formato que pudesse surgir com uma pedra.

Vejo esse recurso sendo usado principalmente em ambientes de CI, onde acho que pode brilhar (como o OP mencionou).

Observe também que, se entendi corretamente, o npm está atualmente trabalhando em um gerenciador de pacotes muito leve específico de CI, que pode não funcionar muito bem com coisas que exigem lógica de negócios pesada, como um conversor de lockfile.

Com relação ao IC:
Meu pensamento inicial foi: avisar ao adicionar um novo pacote com a ferramenta oposta, converter ao fazer uma nova instalação (ou mais conservador: falhar por padrão em uma nova instalação e permitir a conversão por meio de um comando import ou sinalizador de configuração para instalação).

Quando eu trabalhei anteriormente em um ambiente misto de npm / yarn, nós essencialmente faríamos isso manualmente com históricos git. Foi um processo meticuloso e tenho certeza de que não estávamos / não estamos sozinhos nisso.

Quanto à escalabilidade:
Eu gostaria de explicar isso também.
Quando a conversão é realizada, uma árvore de pacote intermediário lógico e físico (se o lockfile tiver uma) é criada. Ao converter para o arquivo de bloqueio desejado, essas árvores são usadas (ou criadas com padrões sãos no caso de estarmos convertendo de yarn e não tivermos uma árvore física).
Desta forma, podemos converter facilmente entre outros tipos de arquivo de bloqueio (tudo o que precisamos fazer é fornecer conversões de / para uma árvore lógica / física para cada tipo).

Obviamente, isso está um pouco à frente dos recursos da ferramenta no momento, mas não vejo a implementação disso como um grande problema.

(quanto à nova ferramenta ci do npm - entendo o que você quer dizer, mas acho que isso está um pouco à frente da discussão atual?)

ou mais conservador: falha por padrão em uma nova instalação e permite a conversão de forma detalhada por meio de um comando de importação

Sim, eu adoraria adicionar essa lógica de conversão ao comando yarn import , parece um recurso útil que pode ser extraído em um pacote separado se / quando implementarmos plug-ins Yarn :) Meus comentários são com foco no comportamento padrão que devemos adotar.

A partir de npm@6 , você deve ser capaz de converter package-lock.json -> yarn.lock sem perdas, sem ter que executar uma instalação primeiro. Deve conter todos os dados de que você precisa, identificadores, etc (npm @ 6 pkglock tem intervalos de versão no campo requires , que corresponde ao que yarn.lock usa?)

Ah, e você também precisa que https://github.com/yarnpkg/yarn/pull/5042 seja enviado antes que isso seja verdade, também, já que o npm não tem sha1 no pkglock em muitos casos.

@arcanis - fantástico! O mesmo aconteceria com um PR com:

  1. Um aviso ao instalar e encontrar um arquivo package-lock.json
  2. Um aviso ao adicionar e encontrar um arquivo package-lock.json
  3. Adicionar a capacidade de converter de package-lock.json por meio do comando import (e excluir o arquivo depois disso)
    Ser aceitável? (só para termos algo que possamos usar para iniciar a conversa sobre detalhes)

@zkat - isso é ótimo sobre npm@6 ! Se depender de mim, eu optaria por usar isso e voltar aos arquivos de manifesto para oferecer suporte a todas as versões de lockfile. Posso perguntar se você está aberto para implementar um comportamento semelhante (ou talvez um pouco diferente) para npm ?

Observe também que, se entendi corretamente, o npm está atualmente trabalhando em um gerenciador de pacotes muito leve específico de CI, que pode não funcionar muito bem com coisas que exigem lógica de negócios pesada, como um conversor de lockfile.

Se por "atualmente trabalhando em" você quer dizer "enviado", sim. =)

Como você sugere, atualmente o carregamento de yarn.locks está além do seu escopo (já que ele não sabe como fazer o layout de árvores de pacotes), mas se todos nós acabarmos com uma biblioteca que pode fazer esse layout, não me oponho a que ela suporte o carregamento yarn.locks. (Idealmente, esta seria uma biblioteca compartilhada entre ele e o Yarn.) Obviamente, para seu caso, ele não deve remover o arquivo de bloqueio existente. É puramente somente leitura no que diz respeito aos metadados do pacote.

Um aviso ao instalar e localizar um arquivo package-lock.json

Estou preocupado que apenas receber avisos quando um tipo de arquivo de bloqueio não suportado existe não vai ajudar com os problemas levantados por @jmorrell que o Heroku está tendo.

Estou preocupado que apenas receber avisos quando um tipo de arquivo de bloqueio não suportado existe não vai ajudar com os problemas levantados por @jmorrell que o Heroku está tendo.

Um aviso seria uma melhoria, mas um erro com boas mensagens seria ideal para usuários imo. Eu só posso falar por mim, mas tenho vários projetos, alguns que usam yarn e outros que usam npm, e muitas vezes me pego digitando o errado para esse projeto. Um erro rápido significa que posso usar imediatamente aquele que deveria usar desde o início.

Se for um aviso, deve ser grande e óbvio. Os usuários do IME são bastante treinados para esperar ignorar a saída de seu gerenciador de pacotes enquanto funcionasse.

Falei com algumas pessoas que têm mais experiência com desenvolvedores iniciantes que, com sorte, irão comentar como é essa experiência para alguém que está apenas começando.

Supõe-se que os sistemas de CI atuem de uma maneira muito determinística, cometendo acidentalmente um lockfile convertido é algo que deveria ser detectado pior no momento PR, agora, CI é tarde demais para isso.

Concordo. Idealmente, no momento em que chega ao serviço de construção / CI, o aplicativo não está em um estado indeterminado. A única maneira que eu me sentiria confortável para não falhar na compilação neste caso seria se houvesse uma maneira aceita para o usuário indicar sua preferência em package.json , mas essa solução também sobrecarrega o usuário.

Estou preocupado que apenas receber avisos quando um tipo de arquivo de bloqueio não suportado existe não vai ajudar com os problemas levantados por @jmorrell que o Heroku está tendo.

Isso os ajudaria avisando aos usuários que eles estão fazendo algo que provavelmente não querem antes de realmente usar o Heroku. Não tenho certeza de quanto isso realmente mudaria os números, mas isso é algo que podemos verificar em algumas semanas e ver se precisamos ir mais longe. E como as mudanças necessárias são relativamente pequenas, essa pode ser uma boa primeira iteração.

Pergunta honesta para aqueles que propõem um aviso: Existe uma situação em que executar yarn install ou yarn add enquanto um package-lock.json está presente não seria um erro? Idem para npm install e yarn.lock

Migrar de npm para Yarn ou de Yarn para npm vem à mente. Eu prefiro evitar adicionar atrito quando se deseja experimentar outros gerenciadores de pacotes.

Uma coisa a se ter em mente é que avisos e erros não são mutuamente exclusivos, ou pelo menos não com o campo engine . Projetos sem gerenciadores de pacotes fixados podem imprimir um aviso e projetos com gerenciadores de pacotes fixados podem apresentar erro. Desta forma, os usuários podem alternar livremente de um gerenciador de pacotes para outro, até que façam sua escolha e configurem seu package.json de acordo.

Outra vantagem do campo engine é permitir que você saiba com certeza qual versão do gerenciador de pacotes deve ser usada. Acho que é configurável em algum lugar, mas com este sistema faria parte do fluxo de trabalho normal.

Outra vantagem do campo engine é permitir que você saiba com certeza qual versão do gerenciador de pacotes deve ser usada. Acho que é configurável em algum lugar, mas com este sistema faria parte do fluxo de trabalho normal.

Existe um campo engine ou você está se referindo a engines ? Não consigo encontrar nenhum documento referente a engine . Peço desculpas se estou faltando alguma coisa.

Oferecemos suporte à especificação de versões no campo engines : https://devcenter.heroku.com/articles/nodejs-support#specifying -an-npm-version

Ex:

  "engines": {
    "npm": "5.6.x"
  }

Existem algumas preocupações que eu tenho ao usar isso para determinar qual gerenciador de pacotes usar:

  • Do jeito que as coisas estão hoje: um número não trivial de usuários tem npm e yarn definidos, ou uma versão npm, mas eles têm yarn.lock . Versões futuras de npm e yarn podem impor isso, mas os usuários que não atualizam com frequência continuarão a usar as versões atuais por um longo tempo.

  • A maioria dos usuários nunca toca nesta configuração. Eles criaram um bifurcação de um texto padrão antigo que especificava o Nó 0.10 , embora usassem tudo o que baixaram de nodejs.org em sua máquina. Isso causa um número incomum de problemas no Heroku.

  • Freqüentemente, as equipes não coordenam quais versões instalam. A versão do Node, npm ou yarn que eles instalaram geralmente é a que estava atualizada quando começaram um projeto ou da última vez que um deles quebrou e os forçou a reinstalar. Não que isso seja ideal, mas meu entendimento é que a maioria dos usuários de npm / yarn são iniciantes, e isso adiciona um novo obstáculo para começar.

Ex: "Clonei o projeto de exemplo hello-world, baixei o Node de https://nodejs.org e não funcionou"

Dito isso, eu adoraria, adoro, adoraria se as ferramentas implementassem versões restritas e gravassem em engines . Isso evitaria muitos dos erros que vejo todos os dias, mas parece uma mudança muito, muito maior.

Dito isso, eu adoraria, adoraria, adoraria se as ferramentas aplicassem versões rígidas e as gravassem em engines. Isso evitaria muitos dos erros que vejo todos os dias, mas parece uma mudança muito, muito maior.

AFAIK Yarn impõe este campo estritamente, a menos que você passe um sinalizador para desabilitá-lo.

Freqüentemente, as equipes não coordenam quais versões instalam. A versão do Node, npm ou yarn que eles instalaram geralmente é a que estava atualizada quando começaram um projeto ou da última vez que um deles quebrou e os forçou a reinstalar.

Isso é muito perigoso, especialmente ao usar o Yarn, pois só garante a consistência nas mesmas versões principais do Yarn.

Não que isso seja ideal, mas meu entendimento é que a maioria dos usuários de npm / yarn são iniciantes, e isso adiciona um novo obstáculo para começar.

Que tal Yarn (e também npm, se eles gostarem da ideia) adicionando uma entrada "yarn": "^<current_version>" no campo engines para ajudar a introduzir alguma segurança sem muito atrito? Podemos adicionar isso automaticamente ao executar yarn init , yarn import ou quando criarmos um arquivo de bloqueio do zero.

Não sei muito sobre o Yarn, mas acho que a melhor solução seria adicionar um analisador package-lock.json ao Yarn e não criar um yarn.lock se ele existir.

Acho que o objetivo final deve ser ter um formato de arquivo de bloqueio compartilhado entre Yarn e npm.

@thatlittlegit Você ficará satisfeito em saber sobre https://github.com/yarnpkg/yarn/pull/5745 . (o npm fará o mesmo ao contrário, então acabaremos em um lugar onde não importa de que tipo de arquivo de bloqueio você está trabalhando ou de qual ferramenta você escolher.)

Editado para adicionar: Um único formato de arquivo de bloqueio não é, eu acho, um resultado provável, pois há diferentes compensações entre os formatos de arquivo de bloqueio e falta de consenso sobre qual deles é o melhor. Acho que ter ambas as ferramentas capazes de entender mutuamente os arquivos de bloqueio uma da outra é suficiente.

Além disso, há uma tonelada de vantagens em ter várias ferramentas usadas ativamente que fazem diferentes compensações, porque isso significa que os casos de uso do usuário podem ser mais bem atendidos do que com uma única solução geral.

@BYK Algum histórico sobre o comportamento do campo do motor provavelmente seria útil aqui:

Em npm @ 1 e npm @ 2 , tínhamos um package.json chamado engineStrict além dos campos engine . Se engineStrict fosse verdadeiro, o campo engine foi usado como _restrição de resolução_ e antes de aplicarmos o intervalo de semver à lista de versões, as versões com engines incompatíveis seriam filtradas. Isso permitiria que você fizesse coisas como npm install foo e recebesse [email protected] mesmo se [email protected] fosse publicado se [email protected] não fosse compatível com sua plataforma. Isso _parece_ desejável, mas na prática era muito confuso, principalmente porque os documentos no site eram apenas para a versão mais recente.

Se engineStrict fosse falso, a resolução era feita sem levar em conta os campos do mecanismo e avisos eram emitidos se o resultado não fosse compatível.

TAMBÉM havia uma opção de configuração engine-strict , que fazia a mesma coisa que a propriedade package.json , mas a aplicava a TODOS os pacotes.

A partir de npm @ 3 , abandonamos o suporte para a propriedade engineStrict package.json e mudamos o comportamento da opção de configuração engine-strict . A opção de configuração agora transforma os avisos que você recebe em erros, mas não afeta a resolução.

Os campos engine são aplicados não apenas para o projeto de nível superior, mas transitivamente. A introdução de um sinalizador de mecanismo yarn implicaria que dependências só podem ser instaladas com yarn e não acho que seja o caso aqui.

Já que na próxima versão yarn devemos ter a capacidade de importar package-lock.json para yarn.lock - eu gostaria de voltar a discutir o problema de aviso / erro.

A meu ver: não acho que haja um bom motivo para um único pacote ter um arquivo package-lock.json e um yarn.lock . A maioria dos projetos que já vi e que têm isso conscientemente veem isso como um problema que precisa ser consertado, em vez de uma situação desejada (mas é claro que estou aberto para ser corrigido).
Pelo que entendi da explicação de engine não será uma boa solução para especificar explicitamente qual gerenciador de pacotes um pacote está usando.
Então, IMO, esta é uma situação que deveria produzir um erro prolixo que convidaria o usuário a excluir um arquivo ou convertê-lo.

No entanto, acho que produzir tal erro seria uma alteração significativa. No lado do yarn, eu proponho começar com um aviso (como mencionado acima) e lentamente descontinuar esse comportamento até a próxima versão principal na qual seria alterado para um erro (talvez adicionando um sinalizador de configuração que permitiria aos dois arquivos existem simultaneamente).

O que todo mundo pensa? @jmorrell , @BYK , @arcanis , @iarna?

Parece estranho para mim que qualquer tipo de projeto deva especificar qual ferramenta de gerenciamento de pacotes deve ser usada. Corrija-me se eu estiver errado, mas vejo o Yarn como um substituto imediato que depende principalmente da preferência do usuário final. Yarn está tentando substituir inteiramente o NPM como o padrão de fato ou está tentando coexistir?

@BrainBacon Você só obtém os benefícios das dependências bloqueadas se todos yarn.lock e alguém executa npm install , essa pessoa ainda pode acabar com um conjunto diferente de dependências. Portanto, não, não depende da preferência do usuário final, infelizmente - de preferência, todos em um projeto usam o mesmo gerenciador de pacotes.

Isso também significa que não faz sentido ter dois arquivos de bloqueio em um projeto. É improvável que eles resolvam para a mesma árvore de dependências e não deixem claro para os contribuidores qual gerenciador de pacotes usar.

(A peça de substituição drop-in era especialmente verdadeira quando o npm não produzia arquivos de bloqueio, já que não havia informações para serem perdidas lá. Também é verdade se # 5745 realmente significa que o Yarn agora pode produzir um arquivo de bloqueio baseado em package-lock.json , mas isso significa apenas que um _projeto_ pode facilmente substituir npm por Yarn. No entanto, como você ainda precisa verificar o novo arquivo de bloqueio, todos os contribuidores precisarão mudar

Corrija-me se eu estiver errado, mas vejo o Yarn como um substituto imediato que depende principalmente da preferência do usuário final.

O fio não é um substituto direto em termos de API exposta. O yarn add <pkg> vs npm install <pkg> é um exemplo óbvio de algo em que fazemos as coisas de maneira diferente. Tendemos a ter o mesmo conjunto de recursos, mas no final são duas ferramentas diferentes e, às vezes, temos soluções diferentes para o mesmo problema.

O yarn.lock vs package-lock.json é uma dessas diferenças e acredito que nem Yarn nem npm estão interessados ​​em usar um único, pois contêm informações diferentes.

No lado do fio, proponho começar com um aviso (como mencionado acima)

Eu ficaria bem com isso. Algo como:

WARN Your project seem to contain lock files (package-lock.json, shrinkwrap.json) generated
WARN by other tools than Yarn. It is advised not to mix package managers, in order to avoid
WARN resolution inconsistencies caused by desynchronized lock files.

Alguém quer abrir um PR?

Eu ficaria feliz em abrir um PR que adiciona um aviso :)

A solução final desejada aqui é um erro útil quando package-lock.json existe + yarn import ? Meu entendimento era que @iarna estava defendendo que cada ferramenta deveria remover / converter o lockfile oposto se ele existir automaticamente.

Qualquer solução seria uma melhoria significativa para os usuários, mas acho que seria melhor se yarn e npm escolhessem a mesma estratégia (embora não seja estritamente necessário se não houver acordo e as pessoas tiverem convicção).

@jmorrell - meu entendimento é que concordamos que a conversão automática é uma má ideia aqui.

Principalmente porque é difícil saber qual deve ser o delta entre os dois arquivos de bloqueio.
Por exemplo. quando vejo o aviso acima como desenvolvedor, o que provavelmente gostaria de fazer é descobrir quando o outro lockfile foi criado, quais pacotes foram adicionados a ele que não foram adicionados ao meu lockfile principal e, em seguida, adicioná-los. Talvez usando a opção import como referência, mas não necessariamente.

Espero que o pessoal de npm concorde com isso.

Idealmente, eu gostaria que o aviso incluísse algo sobre esta ser uma situação obsoleta (não tenho certeza sobre o texto) e que versões futuras do fio produzirão um erro. Talvez um link para alguma documentação detalhada sobre isso e como lidar com isso. @arcanis - você acha que é viável, ou prefere ficar com o comportamento warning ?

Se ambas as ferramentas emitem error quando há vários arquivos de bloqueio, acho que os desenvolvedores perceberão esse problema enquanto ele ainda é "pequeno" e serão capazes de resolvê-lo rapidamente (com a ajuda de importação como referência ou sem) .

@arcanis npm add <pkg> é perfeitamente válido e faz o que Yarn faz 👼

No que diz respeito a pkglock vs yarnlock, a intenção original de package-lock.json era criar um formato que incluísse todos os dados que o gerenciador de pacotes precisava. Na verdade, o pkglock a partir de npm@6 pode ser convertido de forma transparente em um yarn.lock sem a execução de um instalador, pois descreve uma árvore completa com todos os metadados relevantes. Fizemos isso _intencionalmente_ (como o campo requires ) e pedimos feedback das equipes Yarn e pnpm para nos certificarmos de que tudo o que fizemos foi suficiente para ambos usarem como um arquivo de bloqueio importável ou como uma opção alternativa. yarn.lock é, infelizmente, um subconjunto com perdas, então o inverso não é verdadeiro, mas iremos adicionar coisas para importá-lo de qualquer maneira. O npm obedeceria até mesmo às formas de árvore calculadas pelo Yarn (ao contrário do Yarn, que não obedecia).

Na verdade, o pkglock a partir do npm @ 6 pode ser convertido de forma transparente em um yarn.lock sem a execução de um instalador, pois ele descreve uma árvore completa com todos os metadados relevantes.

Não acho que possa (mas talvez eu esteja enganado, fique à vontade para apontar qualquer equívoco). O arquivo de bloqueio do Yarn não oferece suporte por design a vários intervalos resolvendo para uma única versão. Se você tiver vários pacotes, cada um dependendo de lodash@^1.0.0 , todos eles usarão exatamente a mesma versão. Não é apenas uma otimização, mas também como codificamos as coisas em nosso arquivo de bloqueio.

Como o arquivo de bloqueio npm é uma árvore, essa propriedade não é garantida, e vários intervalos idênticos podem acabar usando versões diferentes (o que é bom, já que pode permitir otimizações um pouco melhores ao explorar as regras de resolução do nó). Em tais circunstâncias, a conversão package-lock.json -> yarn.lock teria perdas, já que não teríamos outra escolha a não ser mesclá-los em um único.

Por outro lado, um arquivo de bloqueio Yarn pode ser transformado em um pacote-lock.json relativamente sem problemas, porque nossas regras são um subconjunto mais estrito das suas (nossos intervalos mesclados podem ser transformados em uma árvore sem perda, uma árvore não pode ser transformada em um intervalo mesclado sem perda). Observe que estou falando apenas sobre a árvore de dependência em si, não estou familiarizado com seus campos de metadados.

Para ser sincero, não tenho a certeza se dizemos a mesma coisa ou algo totalmente diferente, só queria esclarecer um pouco a situação 🙂

Idealmente, eu gostaria que o aviso incluísse algo sobre esta ser uma situação obsoleta (não tenho certeza sobre o texto) e que versões futuras do fio produzirão um erro. Talvez um link para alguma documentação detalhada sobre isso e como lidar com isso.

@imsnif Não estou convencido de que isso seja um erro em ambientes não CI (sem dúvida sobre CI - isso é algo que definitivamente deve desencadear um erro). Eu prefiro ficar em um aviso que simplesmente descreva o estado atual e explique por que não é o ideal.

Uma coisa boa é que @jmorrell poderá nos fornecer métricas precisas para ver se o aviso foi suficiente e, com base nisso, escolheremos nosso próximo movimento.

A solução final desejada aqui é um erro útil quando existe pacote-lock.json + importação de yarn?

Sim, junto com o modo "upgrade-to-error-on-CI" * Eu acho que é um primeiro passo razoável!

(* Isso ainda não existe, vou mencioná-lo no # 5773 Yarn 2.0 WG)

@arcanis - Sobre @zkat está se referindo (mas por favor @zkat me corrija se eu estiver errado ou mal-entendido) é que package-lock.json salva a árvore física e lógica, enquanto yarn.lock apenas salva a árvore lógica. Portanto, como mencionado anteriormente, converter package-lock.json => yarn.lock => package-lock.json perderá os dados da árvore física. IMO na maioria dos casos, isso é bom, mas há exceções: por exemplo. dependências agrupadas.

Minha opinião pessoal é que ambos os gerenciadores de pacotes podem se beneficiar da sincronização de sua construção de uma árvore física. Pelo que vi, provavelmente podemos extrair algumas regras bem definidas sobre como uma árvore física é criada e ambas as seguem (de preferência com um módulo mantido por todos os stakeholders). Acho que isso resolverá o problema de compatibilidade, alguns problemas que yarn tem com dependências agrupadas, enquanto ainda permite que cada gerenciador de pacotes mantenha suas peculiaridades exclusivas. (Embora reconheço que eu sou muito novo nessa discussão, então pode haver coisas que eu não saiba - minhas desculpas se estou acordando alguns cães dormindo).

No entanto, para a questão em questão: @arcanis - tentarei oferecer apenas mais um argumento aqui em favor de erros gerais nesta situação, e se você discordar, podemos permanecer com os avisos no que me diz respeito:
Embora seja muito importante que isso seja detectado no nível de CI, acho que um erro seria significativamente mais difícil de depurar (em média) do que um erro no ambiente local do desenvolvedor.
Se um desenvolvedor obtiver um erro em seu ambiente local por usar a ferramenta errada, ele (provavelmente) não dará nem um passo adiante. Eles apenas diriam "oops" e usariam a outra ferramenta. Isso economizará uma quantidade enorme de tempo, em vez de capturá-lo no IC após desenvolver um recurso e, em seguida, retroceder.
Um aviso (como foi mencionado anteriormente aqui) pode ser engolido por alguns outros que os desenvolvedores tendem a ignorar se o status de saída for 0.
O que você acha?

Além disso - na situação que descrevi acima, o arquivo de bloqueio "estrangeiro" pode ser compreensivelmente colocado em .gitignore e, portanto, o IC nem terá a chance de saber sobre isso. Como um desenvolvedor distraído, posso pensar "Bem, isso me dá um aviso obscuro sobre meu ambiente local, mas passa de CI - então provavelmente é apenas um problema local da minha parte - ah, bem"

Um aviso (como foi mencionado anteriormente aqui) pode ser engolido por alguns outros que os desenvolvedores tendem a ignorar se o status de saída for 0.

Meu ponto é que esta afirmação não é apoiada por nenhum dado, embora tenhamos uma maneira de coletar alguns para então tomar uma decisão informada. Nesse contexto, escolher a opção mais radical que vai quebrar o fluxo de trabalho das pessoas me parece um pouco fútil e potencialmente prejudicial 😕

Além disso, acho que você está esquecendo a história do usuário de "Estou usando um gerenciador de pacotes e quero tentar outro", o que acho muito importante para todos os envolvidos, tanto os mantenedores do gerenciador de pacotes quanto os usuários. Não seria ótimo se as pessoas não pudessem testar facilmente o npm 6 em seu projeto Yarn (ou, inversamente, tentar o Yarn em seu projeto npm).

Minha opinião pessoal é que ambos os gerenciadores de pacotes podem se beneficiar da sincronização de sua construção de uma árvore física.

Este é um assunto diferente, mas discordo. Acho que há um equívoco de que Yarn é npm, o que é incorreto. Se você deseja importar um projeto para outro por meio de um comando dedicado, sou totalmente a favor, mas converter silenciosamente (ou ler) arquivos de bloqueio de um formato de terceiros é uma receita para o desastre:

  • irá ignorar os arquivos de configuração
  • irá quebrar a árvore física da próxima vez que um pacote for adicionado / removido
  • qualquer recurso exclusivo de um gerenciador de pacotes não funcionará (áreas de trabalho, substituição de resolução, link :, ...)

Meu ponto é que esta afirmação não é apoiada por nenhum dado, embora tenhamos uma maneira de coletar alguns para então tomar uma decisão informada. Nesse contexto, escolher a opção mais radical que vai quebrar o fluxo de trabalho das pessoas me parece um pouco fútil e potencialmente prejudicial.

Verdadeiro - não é apoiado por nenhum dado. Estou definitivamente especulando aqui (desculpe se não enfatizei isso). Embora possamos ter uma ideia da tendência da correção do aviso, não seremos capazes de ter uma noção de como isso é conveniente para os usuários e se existe uma solução mais conveniente. Se confiarmos nos dados, não acho que haja qualquer resultado diferente de "não houve absolutamente nenhuma mudança na taxa de erro de implantação do Heroku" que nos levará à solução de erro geral.

Eu concordo que é muito importante não quebrar o fluxo de trabalho das pessoas. É por isso que propus o erro como uma alteração significativa em 2.0.0 , com texto no aviso que alertaria o usuário de que esta situação está obsoleta. Também acho que podemos permitir o uso de um parâmetro --force ou config para substituir esse comportamento. (Eu acredito que isso também aborda a sua tentativa de tentar outra preocupação do gerenciador de pacotes?)

Este é um assunto diferente, mas discordo. Acho que há um equívoco de que Yarn é npm, o que é incorreto. Se você deseja importar um projeto para outro por meio de um comando dedicado, sou totalmente a favor, mas converter silenciosamente (ou ler) arquivos de bloqueio de um formato de terceiros é uma receita para o desastre

Acho que você levantou questões importantes aqui que eu adoraria abordar. Mas, como você disse, este é um assunto diferente e não quero atrapalhar a conversa. Talvez possamos discutir isso em uma edição separada?

Acho que a conversa aqui atrapalhou um pouco, por isso quero organizá-la com alguns esclarecimentos e um resumo:

  1. Yarn e npm têm diferentes resoluções e estratégias de criação de árvore física e este é um fator chave para a existência de ambos os projetos.
  2. Os arquivos yarn.lock e package-lock.json foram criados com objetivos específicos em mente e, até onde posso ver, esses objetivos não se alinham totalmente, mas têm algumas sobreposições.
  3. A diferença nesses objetivos não torna um formato superior ao outro em geral, eles apenas trocam coisas diferentes.

Com base nisso, acho que manter os dois formatos é realmente crítico para a inovação e atender a necessidades diferentes. O que é necessário é garantir a portabilidade do projeto com perda mínima de dados entre os gerenciadores de pacotes, sem impor uma estratégia específica de gerenciadores de pacotes para permitir a experimentação livre.

Vejo o reconhecimento e o aviso contra outros arquivos de bloqueio junto com a conversão adequada com uma mensagem clara sobre o que é conservado e o que é perdido como um grande valor para os usuários de cada lado. Portanto, agora a questão aqui nesta edição é qual é o melhor fluxo para usuários que têm um arquivo de bloqueio de pacote em seu repo quando executam o yarn .

Parece que a conversão automática é potencialmente perigosa e a falha na instalação sem saída pode prejudicar algumas pessoas. Que tal exigir que uma configuração seja definida para o yarn para saber que ter um arquivo de bloqueio de pacote se destina ao modo CI? Este é um sinal dos desenvolvedores para o yarn, dizendo "Eu sei o que estou fazendo, por favor, não tente me proteger contra quaisquer descuidos".

Pensamentos?

Que tal exigir que uma configuração seja definida para o yarn para saber que ter um arquivo de bloqueio de pacote se destina ao modo CI? Este é um sinal dos desenvolvedores para o yarn, dizendo "Eu sei o que estou fazendo, por favor, não tente me proteger contra quaisquer descuidos".

@BYK - parece ótimo. Com um acréscimo: como @arcanis me convenceu aqui e no discord, pode ser bom também adicionar um aviso no modo não-ci quando o sinalizador de configuração não está definido. Para que os desenvolvedores tenham a chance de saber que sua construção de CI pode falhar antes de enviar (e também para se proteger contra package-lock.json em .gitignore ).

@arcan é como @imsnif mencionado: pkglock inclui _both_ o layout lógico e físico da árvore. Seguindo a versão lógica da árvore (que inclui os intervalos dos quais desduplicamos), você pode construir um yarn.lock na memória sem nenhuma instalação ou execução da lógica do instalador. Apenas pesquisas de árvore :)

Das notas de versão do NPM 5:

Um novo recurso de arquivo de bloqueio padronizado destinado a compatibilidade entre gerenciadores de pacotes (package-lock.json)

Parece que a equipe do NPM anuncia package-lock.json como a solução universal; é (tecnicamente) possível juntar essa força?

Uma solução que eu gostaria de propor seria "usar apenas package-lock.json quando já existir". É basicamente assim que o NPM "migrou" de um arquivo compactado para um arquivo lock json.

Parece que a equipe do NPM anuncia o package-lock.json como a solução universal; é (tecnicamente) possível juntar essa força?

Já discutimos isso, por favor, verifique o resto do tópico se você não o fez. Isso não vai acontecer no futuro de curto prazo.

Acho que você está esquecendo a história de usuário de "Estou usando um gerenciador de pacotes e quero tentar outro", que acho muito importante para todos os envolvidos

Provavelmente não é uma coisa frequente, a troca de contexto. Eu escolhi Yarn há um tempo e não olhei para trás. Eu acho que é melhor jogar algum peso por trás da seriedade de por que os arquivos de bloqueio estão lá. Torne-o um erro que pode ser desativado, em vez de um aviso que será ignorado. Quando alguém confirma um arquivo de bloqueio, é por um motivo.

Nossas estatísticas mostram que a maioria dos usuários do Yarn também usa o npm. _Projetos_ mistos são incomuns, mas uma única pessoa trabalhando em vários projetos, alguns dos quais são npm e outros são Yarn, é bastante comum. Para complicar ainda mais o problema, os scripts de instalação que executam o npm diretamente são uma coisa.

Eu quero usar yarn, mas a maioria dos projetos em que trabalho tem apenas package-lock.json arquivos. Não consigo adicionar yarn.lock arquivos. yarn import está lento e / ou quebrado. Atualmente meu
_apenas_ opção é livrar-se do fio e mudar para o npm.

Eu entendo que o fio é construído por desenvolvedores apenas de fios para projetos apenas de fios. Mas e o resto de nós?

Ei @Spongman - yarn import não deve ser quebrado. Agora ele deve ser capaz de importar package-lock.json para você. Se você estiver tendo problemas, avise-nos!

Eu fiz # 6103

Ei @Spongman - Eu comentei na questão, este caso específico foi devido a um package-lock.json corrompido. Eu ficaria feliz em saber sobre quaisquer outros problemas.

O npm pode usar esse arquivo package-lock.json perfeitamente. o fio precisa ser mais resiliente.

Respondi isso na outra edição - peço que a discussão prossiga para lá de modo a manter essa questão no tópico. Obrigado!

Eu estava observando atentamente e participando de https://github.com/yarnpkg/yarn/issues/3614 (atualmente com 254: +1: s). Essa questão já foi encerrada e a discussão movida aqui.

Ignorando os desafios práticos, na minha opinião, de longe, o melhor UX seria fornecido por uma opção não mencionada no resumo no topo, mas mencionada por @thatlittlegit :

Acho que o objetivo final deve ser ter um formato de arquivo de bloqueio compartilhado entre Yarn e npm.

Que também é apoiado pelo ponto de @BrainBacon :

Parece estranho para mim que qualquer tipo de projeto deva especificar qual ferramenta de gerenciamento de pacotes deve ser usada.

Novamente, ignorando os desafios práticos por um minuto, o contra-argumento teórico para isso foi feito por @iarna neste tópico (e @jhabidas no outro tópico ):

Há uma tonelada de vantagens em ter várias ferramentas usadas ativamente que fazem diferentes compensações, porque isso significa que os casos de uso do usuário podem ser mais bem atendidos do que com uma única solução geral.

Pessoalmente, não acho que este argumento se deva aplicar neste caso, como fiz em um comentário no outro tópico (com 95: +1: s, 2: -1: s):

Sim, concordo, o Yarn quer manter o seu espaço independente o máximo possível, por isso tem a flexibilidade de proporcionar uma melhor experiência. É por isso que, por exemplo, o CLI do Yarn deliberadamente não é compatível com o NPM.

No entanto, acho que os arquivos de bloqueio estão fora do espaço onde o Yarn pode manter razoavelmente independência. package-lock.json e composer.lock estão comprometidos com o repositório , junto com package.json e composer.json . Esses não são arquivos específicos da ferramenta, mas sim arquivos específicos do projeto que especificam as versões de dependência exatas com as quais o projeto tem garantia de funcionar.

...

Para que o Yarn seja uma ferramenta útil, ele deve permitir que os desenvolvedores sigam os modelos padrão em seus projetos, de forma que o projeto possa permanecer independente de ferramentas. Afinal, é por isso que o Yarn foi criado com base em package.json e não em seu próprio arquivo de dependência separado.

Depois de ler a maior parte deste tópico, ainda concordo com minha avaliação inicial - se o Yarn continuar a consumir o mesmo package.json arquivo de dependência do repositório, idealmente ele deve emitir o mesmo package-lock.json arquivo para o repositório , para que o repositório possa permanecer independente de ferramenta. Se o Yarn lesse suas dependências de yarn.json vez de package.json eu não continuaria fazendo isso.

Eu acredito que devemos admitir que esta é a situação ideal , a experiência do usuário perfeita. No entanto, eu entendo o outro ponto de @iarna :

Um único formato de arquivo de bloqueio não é, eu acho, um resultado provável, pois existem diferentes compensações entre os formatos de arquivo de bloqueio e falta de consenso sobre qual deles é o melhor

(embora eu discorde que "ter ambas as ferramentas capazes de compreender mutuamente os arquivos de bloqueio uma da outra é suficiente").

Se o cenário ideal de permitir que os repositórios sejam agnósticos em relação a ferramentas definitivamente não é alcançável (e vejo os muitos comentários sobre como os diferentes arquivos de bloqueio são construídos de maneiras fundamentalmente diferentes e contêm informações diferentes), então para onde parece que estamos indo palatável, que é:

  • O NPM / Yarn emitirá avisos se detectar o arquivo de bloqueio do outro (e talvez uma opção de configuração para tornar isso um erro)
  • Ambas as ferramentas fornecem mecanismos para converter um arquivo de bloqueio em outro

Não acho que nenhum dos dois deva, em hipótese alguma, converter e deletar o arquivo de bloqueio do outro. Isso significaria que novos desenvolvedores estariam sempre mudando de um para o outro e vice-versa, dependendo de qual ferramenta o desenvolvedor usar (considerando que muitas pessoas se comprometem com git commit -a ).

Também não concordo com o ponto de @imsnif :

Não acho que haja uma boa razão para um único pacote ter um arquivo package-lock.json e um yarn.lock.

Acho que é presunçoso ditar o que um desenvolvedor executa em seu computador ou em seu ambiente de produção. É pelo menos cortês não ser mais restritivo do que você precisa ser. Se o seu projeto é executado apenas por sua equipe de desenvolvedores e todos eles têm exatamente o mesmo software em execução, ótimo. Mas você pode ter um desenvolvedor que acha muito mais fácil usar o NPM do que o Yarn por algum motivo. E, especialmente se você faz software de código aberto, deseja que seja o mais fácil possível para os membros da comunidade começarem a trabalhar. Visto que NPM e Yarn são simplesmente ferramentas para instalar as mesmas dependências de package.json , eles devem funcionar. Um desenvolvedor deve ser capaz de ver package.json , ter uma ferramenta para interpretá-lo e não precisa se preocupar mais. O que costumava ser o caso antes deste conflito de lockfile vir sozinho.

Ei @nottrobin - acho que entendo de onde você está vindo. Se ignorarmos os desafios práticos e as diferenças filosóficas, definitivamente seria melhor para os usuários das várias ferramentas se todos eles consumissem o mesmo arquivo de bloqueio (esta é minha opinião pessoal, é claro).

Mas, uma vez que não podemos ignorar os referidos desafios práticos e principalmente parecemos ter concordado que as diferenças filosóficas têm seu lugar, acho que o compromisso que chegamos (aquele que você descreveu acima) é definitivamente "bom o suficiente".

Observe que uma suposição oculta nesse acordo é que a escolha da ferramenta é feita por projeto, e não por máquina do desenvolvedor ou ambiente de produção.

Observe que uma suposição oculta nesse acordo é que a escolha da ferramenta é feita por projeto, e não por máquina do desenvolvedor ou ambiente de produção.

Sim, acho que isso é o que mais me preocupa - embora eu ache que no cenário que descrevi acima ainda seja possível ter um projeto de apoio tanto ao Yarn quanto ao NPM.

Eu realmente acho que se os dois projetos abandonarem a missão de tentar permitir que um projeto seja agnóstico em relação às ferramentas, eles deveriam parar de compartilhar um arquivo de dependência. O fio deve passar a ler yarn.json vez de package.json . Qualquer outra coisa é apenas bagunçada e confusa.

Se npm lockfiles já tem um superconjunto de relacionamentos de dependência que os lockfiles Yarn suportam, por que não suportar ambos no Yarn? O Yarn pode mudar para o package.json e quaisquer campos adicionais que possam ser desejados pelo Yarn podem ser adicionados no futuro (semelhante a como alguns editores SVG como o Inkscape gerenciam os metadados do editor). Então, o Yarn poderia ter o mesmo formato de dependência que o npm e voltar a ser compatível com o yarn.lock, convertendo os arquivos de bloqueio npm para qualquer estrutura que o Yarn desejasse na memória com perdas.

Eu realmente acho que se os dois projetos abandonarem a missão de tentar permitir que um projeto seja agnóstico em relação às ferramentas, eles deveriam parar de compartilhar um arquivo de dependência. O fio deve passar a ler yarn.json vez de package.json . Qualquer outra coisa é apenas bagunçada e confusa.

Talvez sim, talvez não. Certamente, isso exigiria uma troca massiva de ruptura da ferramenta (fio). Mudanças menos radicais com benefícios mais diretos e mensuráveis ​​foram deixados de lado.

Não estou dizendo que é uma má ideia, estou apenas dizendo que não acho que seja uma ideia prática.

Não estou dizendo que é uma má ideia, estou apenas dizendo que não acho que seja uma ideia prática.

Eu concordo que parece uma grande pergunta. Mas o que estou dizendo é que essa parece ser uma questão central para o projeto.

Até agora, o Yarn era uma ferramenta que os desenvolvedores podiam escolher usar em vez do NPM para instalar dependências do Node para qualquer projeto com package.json . Agora, como você apontou, é necessário que os projetos escolham explicitamente entre Yarn e NPM. Essa é uma grande mudança e não deve ser feita acidentalmente. Este é o ponto crucial para fazer essa chamada.

Em minha opinião, existem 3 maneiras de avançar:

  1. Continue a ser um substituto imediato para o NPM, encontrando uma maneira de alinhar o Yarn com o NPM em todas as interfaces de nível de projeto (padronizar o arquivo de bloqueio)
  2. Deliberadamente diverge do NPM usando interfaces de nível de projeto explicitamente diferentes (por exemplo, yarn.json e yarn.lock )
  3. Duplique no fornecimento de metade da interface NPMs e outra metade da interface diferente. Na verdade, é o mesmo que o ponto 2., mas enquanto olhamos para a maioria das pessoas, como o ponto 1.

Eu acredito que a terceira opção aqui confunde todo o espaço do Node e enfraquece ambas as ferramentas consideravelmente.

Ainda pode ser compatível com as versões anteriores. O Yarn poderia ter um conversor npm lockfile embutido, então quando ele vir o package-lock.json, ele o manterá lá e o converterá para o formato do yarn.lock na memória. Pelo que eu sei, o npm não pode fazer isso porque o arquivo de bloqueio do Yarn tem menos informações do que o npm, então, em minha opinião, seria melhor para o Yarn padronizar com o npm.

@nottrobin , no entanto, acho que você está correto em sua análise:

Agora, como você apontou, é necessário que os projetos escolham explicitamente entre Yarn e NPM. Essa é uma grande mudança e não deve ser feita acidentalmente.

Acho que sempre foi esse o caso, ou pelo menos errou o principal benefício que o Yarn foi inicialmente anunciado para trazer: reprodutibilidade das árvores de dependência. Você pode verificar seu yarn.lock , mas isso é praticamente inútil se outros desenvolvedores adicionarem / removerem dependências sem respeitar esse arquivo de bloqueio.

@nottrobin - concordo com @Vinnl. Como mencionei acima, embora eu não queira dizer a ninguém como eles devem funcionar, acho que usar yarn e npm para instalar dependências no mesmo projeto é um antipadrão.

Embora ambas as ferramentas possam tecnicamente dar muito trabalho para fazer isso funcionar, não acho que isso seja algo que nós, como mantenedores, devamos encorajar. Existem inúmeros outros benefícios em ter arquivos de bloqueio intercambiáveis ​​(como as várias discussões nos diferentes tópicos mostram), mas eu não acho que este seja um deles, pessoalmente.

mas isso é praticamente inútil se outros desenvolvedores adicionar / remover dependências sem respeitar esse arquivo de bloqueio.

Sim, suponho que até certo ponto o Yarn estava naquela água lamacenta desde o início - a existência de yarn.lock já significava que ele tinha parcialmente sua própria interface. Acho que sempre foi uma coisa um pouco complicada de se fazer, o que serviu ao propósito de Yarn de querer que as pessoas fossem de NPM a Yarn, mas não de volta.

Mas foi uma decisão que me senti mais confortável tomando para o meu projeto, porque pelo menos eu sabia que o NPM ainda era totalmente apoiado - uma vez que não fornecia bloqueio em primeiro lugar, ele continuaria a funcionar tão bem como sempre.

Agora isso mudou, porque o NPM bloqueia dependências. Se eu escolher vincular um projeto ao Yarn, irei manter yarn.lock atualizado, e não package-lock.json , portanto, não é mais verdade que alguém pode usar o NPM de forma eficaz no meu projeto.

Parece que você está dizendo que o fio não se destina mais a ser um substituto imediato para o npm? Que só deve ser usado em projetos somente de fios?

Acho que, se for esse o caso, você deve a todos deixar esse fato claro na página inicial do Yarn - use isso ou npm, não ambos.

Parece que você está dizendo que o fio não se destina mais a ser um substituto imediato para o npm?

Nunca foi. A interface de certa forma imitou o npm para tornar mais fácil para os usuários entenderem como usá-lo, mas desde o início algumas coisas funcionaram de forma diferente. A principal razão pela qual algumas pessoas pensaram que era um substituto imediato era que o npm não tinha recursos para comparar.

Agora que o npm está se atualizando em algum aspecto e decide implementar as coisas de maneira diferente, ele simplesmente começa a mostrar que temos abordagens diferentes e tomamos decisões diferentes (por exemplo, o recente recurso de espelho offline npm implementado não é compatível com o existente). Resumindo: nunca foi "seguro", apenas funcionou acidentalmente.

Acho que, se for esse o caso, você deve a todos deixar esse fato claro na página inicial do Yarn - use isso ou npm, não ambos.

Na verdade, temos instruções de migração . Sua observação me fez notar que, infelizmente, contém um parágrafo errado que pode dar às pessoas a impressão errada 🙁 Aceitaríamos de bom grado um PR para alterar este parágrafo para algo mais em linha com nossas recomendações (ou seja, usar o Yarn consistentemente entre as equipes para ter certeza de que todos podem se beneficiar dos vários recursos que podem ser usados ​​pelo projeto).

Nunca foi

err ... você precisa falar com o seu pessoal de marketing, então. https://yarnpkg.com/lang/en/docs/

O Yarn interage diretamente com muitos recursos do npm, incluindo seu formato de metadados de pacote, permitindo uma migração fácil.

Não temos pessoal de marketing, mas aceitamos bons RP 🙃

Neste caso em particular, não parece muito errado. Fazemos interoperabilidade com muitos recursos, mas não com todos eles, e a migração é indolor na maioria dos casos (na pior das hipóteses, está a yarn import distância).

migração é indolor

não estou realmente interessado em migração. estou procurando o que foi prometido aqui (esses caras _definitivamente_ têm pessoal de marketing): https://code.fb.com/web/yarn-a-new-package-manager-for-javascript/

Ele tem o mesmo conjunto de recursos dos fluxos de trabalho existentes, enquanto opera com mais rapidez, segurança e confiabilidade.

fio hoje não é isso.

AFAICT existem 4 classes de usuários aqui:

  • aqueles que _somente_ usam fios em seus projetos,
  • aqueles que compraram o discurso de vendas do facbook (acima), mas ainda não encontraram nenhum desses problemas
  • aqueles que estão tentando contornar as incompatibilidades manualmente convertendo arquivos de bloqueio quando necessário, ou usando outros hacks para fazê-lo funcionar,
  • aqueles que simplesmente desistiram do fio e voltaram para o npm.

Eu realmente não quero estar na última categoria, mas parece que é onde estou sendo empurrado.

@Spongman o que está impedindo você desse último? Provavelmente podemos consertar;)

@Spongman Não sou afiliado ao Yarn, então acho que posso ser um pouco mais direto: realmente não há sentido em afirmar nesta edição que você acha que o texto está errado. Se você acha que o texto está errado, vá para a página do GitHub, clique no botão Editar e envie uma solicitação de pull com melhor texto. arcanis deixou claro acima que eles estão abertos a isso.

(Eu acho que você provavelmente não pode editar a postagem do blog, mas o site é provavelmente o mais importante aqui.)

Posso ver nas respostas de @arcanis que a posição oficial aqui parece ser que Yarn "nunca teve a intenção" de continuar a trabalhar perfeitamente ao lado da NPM.

Mas eu concordo totalmente com @Spongman que essa foi a impressão que Yarn deu, e eu realmente não acho que foi um acidente na época. Essa foi sua genialidade - você poderia ter melhorado a velocidade, segurança, etc., ao mesmo tempo que ainda suportava completamente os padrões oficiais do NPM.

Em qualquer dos casos, esta questão torna a posição do Yarn sobre isso muito mais clara para mim do que era antes e, claro, os mantenedores do Yarn podem escolher tomar a direção que escolherem.

Mas acho que você está subestimando drasticamente o número de pessoas que usaram o Yarn precisamente porque acreditavam que ele mantinha a compatibilidade com o NPM (no nível do projeto) e nunca teriam feito a troca de outra forma. Eu acredito que os 254: +1: se 10: coração: s em https://github.com/yarnpkg/yarn/issues/3614 e os 57 votos positivos em "

Se Yarn abdicar de qualquer responsabilidade nessa frente, acho que perderá não apenas @Spongman e minhas equipes, mas muitos outros.

Francamente, eu realmente não entendo o problema que você tem em usar apenas Yarn ou apenas NPM. O que você está dizendo é basicamente "ei, não posso forçar minha equipe a usar o Yarn, então vou forçá-los a usar o npm". Isso não faz sentido para mim. Se você usar os recursos do Yarn, faça com que todos usem o Yarn, e se quiser usar os recursos do npm, faça com que todos usem o npm. É tão simples quanto isso.

Qualquer meio-termo significa que pelo menos suas construções não são consistentes em sua equipe, o que vai contra a premissa do Yarn, como mencionado antes. Um de seus engenheiros poderia começar a usar os espaços de trabalho e funcionaria, mas seria interrompido no npm. O mesmo do espelho offline. O mesmo para as resoluções de dependência. Pior ainda, como alguns campos são totalmente desconhecidos pelo npm, ele silenciosamente faria a coisa errada.

Quanto à comunicação, o post do blog do fb não menciona uma substituição imediata. Deixe-me citar a parte em que o Yarn é introduzido. Ele literalmente diz que substitui o fluxo de trabalho. Eu acho que você se confundiu com o "permanece compatível com o registro npm", que é um ponto justo que você deve trazer para o npm, não para nós (há o npm cli, o registro npm e, claro, o próprio npm Inc).

Yarn é um novo gerenciador de pacotes que substitui o fluxo de trabalho existente para o cliente npm ou outros gerenciadores de pacotes, enquanto permanece compatível com o registro npm.


o que está impedindo você desse último? Provavelmente podemos consertar;)

@zkat Isso é útil, obrigado.

@nottrobin - Eu não posso falar sobre as intenções originais do yarn porque eu não estava por perto na época. No entanto, eu estava trabalhando em um ambiente misto de yarn / npm com várias dezenas de repositórios.

Posso dizer que era perfeitamente claro para todos os desenvolvedores envolvidos naquela época que a escolha de yarn / npm era uma escolha por repo, assim como a escolha de express / hapi, mobx / redux, etc. Isso se tornou ainda mais claro quando npm @ 5 saiu com seu próprio formato de arquivo de bloqueio e alguns desenvolvedores decidiram começar a usá-lo com novos repositórios.

Quando um desenvolvedor instalaria uma dependência com a ferramenta errada, ele criaria uma bagunça mesmo antes do npm @ 5 , porque essa dependência não seria travada de forma consistente. Isso causou problemas em nossos vários ambientes e ficou muito claro para todos os envolvidos que isso era um erro *.

Sei que isso pode ser confuso - e entendo que isso pode não ser 100% claro para todos, sem culpa própria, mas não acho que seja certo mudar drasticamente a ferramenta para se adequar a esse mal-entendido. A meu ver, o fio é uma queda em substituição ao npm em uma base por repo em vez de por caixa.

* Concedido, aquela situação particular de múltiplos repositórios fora do espaço de trabalho com ferramentas mistas de fio / npm não era ideal em um nível Humano ao invés de um nível técnico para exatamente esses potenciais de erro e foi eventualmente corrigido. Eu uso este exemplo aqui para mostrar que as duas ferramentas podem funcionar lado a lado se abordadas corretamente.

Francamente, eu realmente não entendo o problema que você tem em usar apenas Yarn ou apenas NPM.

Sim, você @arcanis e @imsnif deixaram claro que não entende. O único ponto que estou enfatizando é que muitas pessoas (olhe para: +1: s) fizeram a mesma "interpretação errada" e querem que o Yarn trabalhe ao lado do NPM, independentemente de você entender isso ou não. Se Yarn não é a ferramenta para nós, que seja.

(Apenas um ponto final - @imsnif é totalmente ridículo comparar uma ferramenta para instalar dependências do Node a uma escolha de projeto como express vs hapi, mobx vs redux. Essas são características fundamentais do seu aplicativo. Se você não consegue ver a diferença óbvia, não é de admirar que você não entenda meu ponto.)

De qualquer forma, acabei agora. Acho que expus meu ponto da melhor maneira possível.

Para projetos de código aberto, nunca é uma questão de forçar "a equipe" a usar yarn ou npm. É uma questão de saber o que é mais conveniente para todos. No mundo real, o npm é rei, então, a menos que o fio funcione bem em um mundo do npm, ele está morto.

^ Este

Receio que isso também seja um equívoco. Durante o ano passado, o Yarn passou de 20% da quantidade total de solicitações ao registro do NPM para 40% em abril . A última vez que ouvi as estatísticas (direto do pessoal do npm, já que nossas estatísticas quebraram recentemente quando o registro do npm foi para o Cloudflare), era cerca de 48% das solicitações. No mundo real real, Yarn e npm coexistem, pura e simplesmente.

Agora, eu apreciaria se pudéssemos voltar ao tópico em questão, que é: quem está disposto a escrever um PR para escrever um aviso quando detectamos um arquivo package-lock.json no momento da instalação? Obrigado.

Incrível: heart_eyes:

Entre isso e seu trabalho em yarn import , podemos encerrar este problema então?

Pensei em esperar que @jmorrell nos desse algumas estatísticas de como isso afeta o problema no Heroku para que possamos decidir se isso é suficiente ou se gostaríamos de mudar algo (aviso / erro, etc.) wdyt?

EDIT: afaik o aviso ainda não foi divulgado, então ainda temos algum tempo para esperar

Receio que isso também seja um equívoco.

Como assim? O volume de tráfego no npm não diz nada sobre se o projeto é ou não de código aberto.

uma avaliação mais precisa seria contar quais projetos github têm 0,1 ou 2 de (yarn.lock, package-lock.json). pessoalmente, eu _nunca_ vi um projeto de código aberto (de qualquer tamanho apreciável) no github que tem um arquivo yarn.lock e _no_ package-lock.json (exceto o óbvio).

IMO se você vai manter arquivos de bloqueio separados, então AMBOS os gerenciadores de pacotes devem detectar o arquivo de bloqueio do outro e ERROR (possivelmente com um sinalizador de substituição).

Todos - Peço gentilmente que permaneçamos no assunto e deixemos qualquer comentário não diretamente relacionado off-line (por exemplo, nosso canal Discord). Há muitas pessoas inscritas neste tópico e, para ser justo, acho que a discussão sobre o fio npm <> não pertence aqui. Obrigado!

Eu não li a banda inteira, mas o usuário IHMO deve ser pelo menos notificado de que há uma ambigüidade:

se o npm vir um arquivo yarn.lock, então o npm deve imprimir algo como:
"AVISO: este projeto parece usar yarn, talvez você deva usar 'yarn' em vez de 'npm install'"

se o yarn encontrar o arquivo package-lock.json, o yarn deverá imprimir algo como:
"AVISO: este projeto parece usar npm, talvez você deva usar 'npm install' em vez de 'yarn'"

E como sugerido acima, uma maneira de "preferir" o gerenciador de pacotes (em package.json).

Posso dizer que estava perfeitamente claro para todos os desenvolvedores envolvidos naquela época que a escolha de yarn / npm era uma escolha por repo, assim como a escolha de express / hapi, mobx / redux, etc.

Isso não estava nada claro para mim. Até agora eu pensava que era uma escolha local do desenvolvedor, e vários desenvolvedores poderiam coexistir em um único repositório usando o que quisessem, embora fosse _um pouco mais conveniente_ usar apenas um consistentemente. Os exemplos express / hapi etc são bons e deixam claro que não é uma escolha. Isso deve ter mais visibilidade.

Adicione um campo em package.json para indicar qual gerenciador de pacotes um projeto deve usar

"package-manager": "yarn"

Acho que essa é a melhor solução, se for implementada em todos os gerenciadores de pacotes.

Os gerenciadores de pacotes DEVEM então se recusar 100% a continuar se forem chamados no projeto errado, da mesma forma que você esperaria um erro se solicitasse redux, mas tentasse chamar funções mobx nele. Eles devem emitir um erro, não um aviso, e informar ao usuário como proceder com o gerenciador de pacotes correto.

Adicione um campo em package.json para indicar qual gerenciador de pacotes um projeto deve usar
"package-manager": "yarn"

Acho que essa é a melhor solução, se for implementada em todos os gerenciadores de pacotes.

Se você quiser que o npm considere isso, eu o encorajo a abrir uma discussão no local apropriado , mas direi que não gosto dessa direção. Eu gostaria de ver convergência entre gerenciadores de pacotes, não divergência.

Eu recomendaria contra algum novo campo "gerenciador de pacotes", em vez de recomendar a estrofe engines que já tem a técnica anterior.

Os documentos yarn e npm mencionam (de passagem) o uso de engines.npm e engines.yarn para especificar as versões de cada um que devem ser usados. O fio vai até mesmo dar erro se a versão do fio não satisfizer engines.yarn .

https://yarnpkg.com/en/docs/package-json#engines -
https://docs.npmjs.com/files/package.json#engines

Mesmo que nem npm nem yarn verifique engines para o gerenciador "concorrente" (o que seria bom), usar este campo ainda é uma ótima maneira de comunicar a outros desenvolvedores qual gerenciador deve ser usado. (se a existência de package-lock.json ou yarn.lock não é uma pista suficiente)

Eu gostaria de ver convergência entre gerenciadores de pacotes, não divergência.

Acordado. Ou convergência ou recusa.

mas o meio-termo ambíguo e errôneo atual é prejudicial.

Ainda acho que apenas lançar um erro na presença do lockfile dos outros exigiria o mínimo de atrito para os projetos existentes.

Se você quiser que o npm considere isso, eu o encorajo a abrir uma discussão no local apropriado

Obrigado, acabei de me inscrever. Há um tópico recente nesta direção: https://npm.community/t/npm-install-should-warn-about-the-presence-of-yarn-lock-files/1822

Meu voto é para errar o ponto final em vez de apenas avisar, então não tenho certeza se devo acrescentar a esse tópico de começar um novo.

Eu gostaria de ver convergência entre gerenciadores de pacotes, não divergência.

O mesmo aqui. Embora sejam incompatíveis no momento, então a divergência já aconteceu e já está causando atrito a muitos usuários e projetos.

Qualquer convergência resultante de conversas adicionais entre as equipes levará tempo. Quando chegar, os erros propostos podem ser eliminados e os usuários podem começar a alternar e misturar gerenciadores de pacotes sem problemas.

Adicionar os erros agora evita mais confusão e não interrompe os esforços na direção da convergência.

Eu recomendaria contra algum novo campo "gerenciador de pacotes", em vez de recomendar a estrofe de engines existentes que já tem a técnica anterior.

Isso parece razoável. Não estou preso a nenhum método específico para detectar a presença de um gerenciador de pacotes incompatível.


Para adicionar ilustração, meu caso de uso em particular é gatsbyjs. A situação é exatamente a mesma relatada por @gaearon aqui :

Para criar usuários do aplicativo React, isso é extremamente confuso porque seu projeto é criado com Yarn (se Yarn existir no sistema), mas eles seguem os documentos de alguma biblioteca que lhes diz para instalar o npm, e isso destrói a árvore inteira.

Para evitar esse problema, mesmo que gatsby use fios, ele também adiciona package-lock.json aos iniciadores padrão . Mas então os usuários acabam com os arquivos de bloqueio e começam a ver avisos. É fácil excluir apenas um deles, mas atrapalha a experiência de integração.

Obrigado a todos por sua contribuição.

@jmorrell - https://github.com/yarnpkg/yarn/pull/5920 foi lançado em 1.9.2 em 25 de julho. Faz pouco mais de um mês, eu sei que não é muito tempo (e certamente não todo mundo atualizou) - mas você talvez tenha alguma ideia para compartilhar sobre os erros de double-lockfile no Heroku desde então?

@imsnif Obrigado pelo lembrete por e-mail! Desculpe por perder a atualização aqui.

Aqui está um gráfico do número de aplicativos que tiveram essa falha específica a cada semana em 2018.

(Eu editei a escala y, mas isso representa centenas de desenvolvedores e mostra a tendência)

two-lockfile failures

  1. A queda em julho vem de um problema não relacionado com o S3

  2. Observando a tendência após 25 de julho, o aviso parece ter tido um efeito substancial no número de pessoas que experimentaram esse erro. Estou um tanto surpreso com a magnitude da mudança.

@jmorrell - isso é realmente ótimo!
Admito que também estou bastante surpreso com isso.

Acho (do lado do fio) que esse problema pode ser considerado resolvido. Você concorda?

Ainda acho que o conselho de remover package-lock.json para corrigir o erro é enganoso - em geral, isso resultará em um conjunto diferente de versões de pacote sendo usado e (novamente, em geral) levará a incompatibilidades e quebras. além disso, esse conselho só é útil para aqueles que tomam decisões sobre qual gerenciador de pacotes um projeto está usando. contribuidores gerais seguindo este conselho também terão problemas.

IMO se um package-lock.json existe e yarn não pode garantir que as versões que ele instala são as mesmas que npm instalaria, então ele deve falhar com um erro .

Obrigado novamente por sua contribuição @Spongman. Acho que tudo isso foi bem discutido no (muito longo) tópico acima de nós e não acho que faça sentido reiniciá-lo novamente. Acho que todos nós entendemos sua posição. Obrigado por participar.

A menos que @jmorrell me diga o contrário na próxima semana ou depois, considerarei isso concluído e encerrarei este problema.

@imsnif Tomando um caminho diferente e olhando para as falhas de setembro até agora (1 de setembro - 20 de setembro), esta ainda é a razão número 1 pela qual o Node constrói no Heroku falhou. Isso acontece duas vezes mais que o próximo caso de falha conhecido mais comum: package.json sendo JSON inválido. Mais uma vez redigindo números exatos, aqui está como ele se compara a outras questões.

node build failures september 1 - 20 2018

Não vi nenhum movimento do npm sobre isso, então vou criar um PR adicionando um aviso lá também e ver se ele é aceito.

Acho (do lado do fio) que esse problema pode ser considerado resolvido. Você concorda?

Não acho que isso tenha sido resolvido para os usuários, e a experiência do usuário ainda não é boa. Mas posso ver como os números mudam uma vez que o npm também fornece feedback para um usuário que está acertando o caso.

Deixarei que você escolha se deseja encerrar ou fazer outras alterações. Tenho o prazer de abrir um novo problema em alguns meses, se isso ainda for um grande problema para os usuários.

@jmorrell - visto que esse assunto está chamando muita atenção e a conversa continua recomeçando e até se repetindo, acho que seria melhor encerrá-la agora com as informações que temos.

Se, com o npm também fornecendo um aviso, ainda virmos um problema, eu definitivamente estaria disposto a iniciar a discussão sobre o erro novamente (ou procurar outras soluções). Por favor, faça ping em mim pessoalmente nesse caso.

Obrigado por trazer isso à tona, contribuir e fazer todas essas mudanças acontecerem! Eu pessoalmente acho que o fio é melhor depois desse problema.

Esta página foi útil?
0 / 5 - 0 avaliações