[{"data":1,"prerenderedAt":253},["ShallowReactive",2],{"paleta":3,"caso-painel-erp":28,"viz-painel-erp":242},{"projetos":4,"posts":27},[5,9,13,16,20,23],{"path":6,"title":7,"contexto":8},"\u002Fprojetos\u002Fkravva","Kravva","Produto próprio",{"path":10,"title":11,"contexto":12},"\u002Fprojetos\u002Fonboarding-erp","Onboarding digital de um ERP financeiro","Consultoria PJ",{"path":14,"title":15,"contexto":12},"\u002Fprojetos\u002Fpainel-erp","Painel administrativo do ERP",{"path":17,"title":18,"contexto":19},"\u002Fprojetos\u002Fligafest","Ingresso em grupo da LigaFest","LigaMagic · CLT",{"path":21,"title":22,"contexto":19},"\u002Fprojetos\u002Fcircuitos-ligamagic","Circuitos LigaMagic e LigaPokémon",{"path":24,"title":25,"contexto":26},"\u002Fprojetos\u002Fblippy","Blippy","Projeto pessoal",[],{"id":29,"title":15,"body":30,"contexto":12,"cor":207,"description":208,"destaque":209,"extension":210,"link":211,"meta":212,"navigation":213,"numeros":214,"ordem":195,"papel":227,"path":14,"periodo":228,"resumo":229,"seo":230,"stack":231,"stem":240,"__hash__":241},"projetos\u002Fprojetos\u002Fpainel-erp.md",{"type":31,"value":32,"toc":192},"minimark",[33,38,42,45,58,62,67,70,84,87,91,99,103,106,110,118,137,140,144,151,157,163,169,173,176,179,183,186,189],[34,35,37],"h2",{"id":36},"o-problema","O problema",[39,40,41],"p",{},"O ERP financeiro é um monorepo grande, com várias gerações convivendo. Tem um MVC histórico em .NET Framework, APIs e hosts em .NET moderno, um console de processamento, bibliotecas compartilhadas e, dentro disso tudo, uma SPA administrativa em Vue 3. Muita gente commita ali ao mesmo tempo: foram mais de 3 mil commits no período em que trabalhei.",[39,43,44],{},"Três problemas apareciam juntos:",[46,47,48,52,55],"ul",{},[49,50,51],"li",{},"Telas importantes ainda viviam no MVC, mas não dava para desligar o legado de uma vez: clientes, rotinas e regras dependiam dele.",[49,53,54],{},"Áreas administrativas novas precisavam nascer na SPA, conversando com serviços que outros fronts também consomem.",[49,56,57],{},"O ciclo de desenvolvimento era lento, e ninguém sabia dizer em qual etapa o tempo ia embora.",[34,59,61],{"id":60},"o-que-eu-fiz","O que eu fiz",[63,64,66],"h3",{"id":65},"migração-por-partes-não-por-big-bang","Migração por partes, não por big bang",[39,68,69],{},"Levei uma área do MVC para a SPA sem quebrar quem ainda usava o caminho antigo. A mudança atravessou as camadas:",[46,71,72,75,78,81],{},[49,73,74],{},"redirecionamento no MVC;",[49,76,77],{},"rotas, menu e tipos na SPA;",[49,79,80],{},"gates de migração na camada de negócio compartilhada;",[49,82,83],{},"rotinas compatíveis no back-end em .NET, com testes.",[39,85,86],{},"O legado continua de pé enquanto houver consumidor. Cada superfície migra quando está pronta.",[63,88,90],{"id":89},"gestão-de-contratos-e-termos","Gestão de contratos e termos",[39,92,93,94,98],{},"Construí a área administrativa para consultar e gerir contratos e o estado de aceite dos termos: telas, entrada no menu, integração com a API e mocks para testar. A capacidade foi liberada por ",[95,96,97],"termo",{"id":97},"feature flag",". A SPA compõe a experiência; quem decide e persiste é o back-end, o mesmo que atende o onboarding.",[63,100,102],{"id":101},"um-shell-com-variantes-de-navegação","Um shell com variantes de navegação",[39,104,105],{},"Para não duplicar menus e layout a cada variante da SPA, separei três coisas: a escolha da variante, o contrato de navegação (o que cada variante oferece) e um shell visual comum. Assim, uma variante nova da SPA vira configuração, sem copiar o layout inteiro.",[63,107,109],{"id":108},"medir-antes-de-otimizar","Medir antes de otimizar",[39,111,112,113,117],{},"Antes de mexer em qualquer configuração, criei ",[95,114,116],{"id":115},"benchmark","benchmarks"," reproduzíveis de três jornadas: subir o ambiente e abrir o app no navegador, gerar o build e rodar os testes. Com os números na mão:",[46,119,120,123,126,129],{},[49,121,122],{},"separei a validação do empacotamento;",[49,124,125],{},"deixei o build sequencial como opção;",[49,127,128],{},"otimizei a configuração do Vite e passei a carregar alguns recursos só quando são usados;",[49,130,131,132,136],{},"montei um CI experimental com jobs paralelos e testes divididos em ",[95,133,135],{"id":134},"shard","shards",".",[138,139],"viz-build",{},[34,141,143],{"id":142},"decisões-e-trade-offs","Decisões e trade-offs",[39,145,146,150],{},[147,148,149],"strong",{},"Medir jornadas reais, não o tempo percebido."," \"O build está lento\" não diz o que fazer. Benchmark com mesma máquina, mesmos comandos e mediana de várias rodadas diz. O custo é tempo gasto montando o harness antes da primeira otimização.",[39,152,153,156],{},[147,154,155],{},"CI paralelo encurta a espera, mas não é de graça."," Jobs independentes terminam antes, só que cada um paga o próprio setup. A espera de quem abriu o PR cai, e os minutos totais de runner podem subir. Por isso o CI ficou como experimento, documentado com esse custo, e não substituiu o pipeline oficial.",[39,158,159,162],{},[147,160,161],{},"Feature flag e migração por superfície."," Liberar por etapas reduz o risco, mas deixa dois caminhos vivos por um tempo. Esse custo precisa de dono e de data para acabar.",[39,164,165,168],{},[147,166,167],{},"Shell compartilhado com contrato de navegação."," Centralizar evita menus duplicados. O custo é que mudar o contrato exige revisar todas as variantes.",[34,170,172],{"id":171},"resultado","Resultado",[39,174,175],{},"Em benchmark local, o build da SPA caiu de 223 s para 130 s, e o build da SPA com a biblioteca de componentes caiu de 246 s para 175 s. A jornada de desenvolvimento no navegador passou de cerca de 70 s para cerca de 38 s, na mediana. São medições locais com amostra pequena, e a proposta ainda está em validação com o time. Não é ganho de produção.",[39,177,178],{},"A área migrada e a gestão de contratos e termos estão na SPA, com testes, convivendo com o MVC enquanto ele for necessário.",[34,180,182],{"id":181},"o-que-eu-faria-diferente","O que eu faria diferente",[39,184,185],{},"Faria cada métrica opcional do benchmark entrar explicitamente no critério de sucesso. Hoje, uma métrica habilitada pode piorar sem reprovar a execução.",[39,187,188],{},"Faria o filtro de caminhos do workflow cobrir também as mudanças no host MVC, que podem afetar a SPA.",[39,190,191],{},"Antes de propor o CI paralelo como padrão, coletaria uma amostra maior e pareada, comparando a espera e os minutos de runner no mesmo período.",{"title":193,"searchDepth":194,"depth":195,"links":196},"",2,3,[197,198,204,205,206],{"id":36,"depth":194,"text":37},{"id":60,"depth":194,"text":61,"children":199},[200,201,202,203],{"id":65,"depth":195,"text":66},{"id":89,"depth":195,"text":90},{"id":101,"depth":195,"text":102},{"id":108,"depth":195,"text":109},{"id":142,"depth":194,"text":143},{"id":171,"depth":194,"text":172},{"id":181,"depth":194,"text":182},"oklch(0.72 0.14 185)","SPA Vue 3 dentro de um monorepo .NET com MVC legado: migração de telas sem big bang, gestão de contratos e termos, e um build medido antes de ser otimizado.","Build de 223 s para 130 s, medido antes de otimizar","md",null,{},true,[215,218,221,224],{"valor":216,"rotulo":217},"218","commits meus na SPA (~23% do período)",{"valor":219,"rotulo":220},"223 → 130 s","build da SPA, em benchmark local",{"valor":222,"rotulo":223},"~70 → ~38 s","jornada de dev no navegador (mediana)",{"valor":225,"rotulo":226},"68","arquivos de teste tocados","Desenvolvedor full stack, um dos principais contribuidores da SPA","2026","Uma SPA Vue 3 que convive com um MVC legado dentro de um monorepo .NET. Migrei telas por partes, entreguei a gestão de contratos e termos e medi o build antes de otimizá-lo.",{"title":15,"description":208},[232,233,234,235,236,237,238,239],"Vue 3","TypeScript","Vite","Pinia","Element Plus","C#",".NET","GitHub Actions","projetos\u002Fpainel-erp","kZWn-oxLWldfp2onp8MH_j1SXn8Zy6IG-6BbSO8sVAo",[243,245,246,247,249,251],{"path":6,"title":7,"ordem":244},1,{"path":10,"title":11,"ordem":194},{"path":14,"title":15,"ordem":195},{"path":17,"title":18,"ordem":248},4,{"path":21,"title":22,"ordem":250},5,{"path":24,"title":25,"ordem":252},6,1791915291203]