Scripting pode não ser uma demanda corriqueira, mas há momentos em que sua flexibilidade faz jus à sua utilização. Seja para deixar alguma pequena parte de sua aplicação mais flexível ou para poder suportar extensibilidade, há cenários bons para seu uso. Hoje vou abordar como usar o JSRT (Javascript Runtime) da Microsoft, motor do Microsoft Edge, o Chakra em uma aplicação .NET Core, rodando em um container linux com Docker.
O projeto
Após aventurar-me com Jint, um excelente interpretador, senti falta de algum mecanismo que oferecesse uma implementação mais recente, que me permitisse usar elementos do ECMA Script 6, pelo menos.
Isso tudo aconteceu por conta de um utilitário que desenvolvi na semana passada. Sua função é analisar receber dados em alguns formatos dinâmicos e realizar uma série de análises. Como se não bastasse, o input poderia conter qualquer tipo de complexidade não prevista, já que o usuário não era capaz de entregar um mesmo formato uniforme. Meu papel era consolidar esses dados em um outro formato, este já predefinido, de exportação. As série de análises precisavam ser realizadas e definitivamente eu não tinha informações suficientes para decidir quais regras seriam aplicadas a cada cenário (tínhamos essa pessoa na empresa, mas não havia muito tempo). Nesse momento busquei algumas alternativas e no final, o casamento do Jint (Javascript Interpreter for .NET) com o Monaco Editor (Editor de textos, usado no VSCode) fizeram da solução algo que eu pudesse entregar qualidade e flexibilidade. Esse foi mais um projeto relâmpago, daqueles que você torra 80 horas em uma única semana, mas dessa vez não era uma PoC. Dessa vez era um utilitário para dar suporte a um dos nossos produtos.
Mas, como nem tudo são flores, embora eu não tenha citado, na UI, mais especificamente no editor de código, eu estava usando recursos de typescript nativos do Monaco, permitindo-me tipar minhas variáveis e parâmetros, com base em Type Definitions do TypeScript. Algo muito prático, e fácil de se fazer com o Monaco Editor. Por sua vez, ganhei code completion automaticamente, como mostra a imagem abaixo.
O ponto negativo da solução é que o Jint implementa ECMA 5.1 portanto não tenho a possibilidade de usar Tipos, assim vemos na linha 2 um comentário. Na prática alterno o comentário entre essas linhas na hora de salvar/editar, como o editor suporta Tipos mas o runtime não suporta, esse workaround foi necessário. Um problema, um débito, que só poderia ser sanado com outro runtime ou uma versão mais recente do Jint. Como eu era o único usuário dessa ferramenta, pude me dar ao luxo de usá-la assim e adiar a escolha de um runtime que me permitisse no mínimo usar as mesmas features do editor.
Chakra Core
Como disse no post Como definir a Arquitetura de um Software “evite manter débitos técnicos por muito tempo. Destrua-os! Muitas vezes nós mesmos os criamos, quando por algum motivo, deixamos de fazer a coisa certa para fazer o mais rápido. Para minimizar esse tipo de ocorrência, é importante facilitar a mudança e até promovê-la.“. Assim o fiz, e nesse domingo testei alternativas para o runtime. Algumas só funcionaram no windows, outras exigiam dependências mas não reportavam onde buscá-las, por fim, olhei para o JavaScriptengineSwitcher, projeto no qual eu já havia navegado, mas não chamou minha atenção na época. Hoje revisitei-o e dei uma chance para o ChakraCore e obtive sucesso!
Assim, abaixo segue um passo a passo sobre como usar o Chakra Core com .NET e Docker:
Requisitos:
- Projeto .NET Core Console Application baseado no runtime 2.0 do .NET Core.
- Adicione suporte a docker (linux) ao projeto console.
Na imagem temos os demais passos:
- Adicionar referências nuget:
- JavaScriptEngineSwitcher.ChakraCore
- JavaScriptEngineSwitcher.ChakraCore.Native.win-x64 (caso queira executar no windows ou windows containers)
- JavaScriptEngineSwitcher.ChakraCore.Native.linux-x64 (caso queira executar no linux ou linux containers)
- Adicione o using adequado
- Adicione um exemplo de código (no exemplo da imagem acime e do código abaixo, uso arrow functions).
O código está aqui:
using System; using System.Threading.Tasks; using JavaScriptEngineSwitcher.ChakraCore; namespace JsOnDotNetConsoleApp { class Program { static void Main(string[] args) { using (ChakraCoreJsEngine engine = new ChakraCoreJsEngine()) { string text = engine.Evaluate<string>(@" let x = () => (new Date()).toString(); x(); "); } } } }
Conclusão
Já foi complicado realizar esse tipo de coisa, mas hoje essa dinâmica está mais fácil do que nunca, e já temos muitos frameworks que dão suporte a este tipo de implementação, em que preciso de dinamismo pela natureza incerta do que vou trabalhar.
Antes que me esqueça, o projeto foi um sucesso, mesmo usando Jint, no entanto estar preso ao ECMA antigo me deixou incomodado. Ainda preciso avaliar mais alguns aspectos, como performance, consumo de recursos (memória, cpu etc) para poder me decidir. Ah, essa nomenclatura que você vê no code completion não é minha. É um mapeamento direto com o XML que tenho de manipular.
Por hoje é só!
0 comentários