Executando verificação de segurança...
2

Era pra ser só um fim de semana estudando Serverless...

Nesse fim de semana fui me aventurar no mundo Serverless, e acabei me deparando com um erro que me custou mais ou menos 8 horas para resolver e conseguir realmente me aventurar no mundo Serverless. Risos.

Então vou contar um pouco do que aconteceu e como resolvi e espero que seja de ajuda pra alguns de vocês.

Antes de partir pra história, esse artigo também pode servir como tutorial para configurar um ambiente Serverless offline para NodeJS + Typescript.

Se você quiser pular logo pra parte da resolução procure pelo subtítulo Enfim a resolução

Como tudo começou

Depois de bater o olho na documentação do Serverless Framework, assistindo alguns vídeos do Ignite (Bootcamp da Rocketseat) fui iniciar o desenvolvimento de um projeto simples, uma função serverless que gera certificados de um curso. Mas os vídeos são de 2021 se não me engano, de lá pra cá várias libs passaram por umas boas atualizações. Porém, eu não queria fazer o downgrade de nada, pra conseguir desenvolver o projeto com as tecnologias atualizadas, e lá fui eu...

  • Instalei o Serverless na máquina
  • Iniciei um projeto utilizando o template aws-nodejs-typescript
  • Instalei as dependências
  • Instalei o plugin serverless-offline
  • Rodei o comando serverless offline para rodar a aplicação padrão e ver se estava tudo funcionando e... ERRO

Mais precisamente, esse erro aqui...

Error: 
You installed esbuild for another platform than the one you're currently using.
This won't work because esbuild is written with native code and needs to
install a platform-specific binary executable.

Specifically the "@esbuild/darwin-arm64" package is present but this platform
needs the "@esbuild/darwin-x64" package instead. People often get into this
situation by installing esbuild with npm running inside of Rosetta 2 and then
trying to use it with node running outside of Rosetta 2, or vice versa (Rosetta
2 is Apple's on-the-fly x86_64-to-arm64 translation service).

If you are installing with npm, you can try ensuring that both npm and node are
not running under Rosetta 2 and then reinstalling esbuild. This likely involves
changing how you installed npm and/or node. For example, installing node with
the universal installer here should work: https://nodejs.org/en/download/. Or
you could consider using yarn instead of npm which has built-in support for
installing a package on multiple platforms simultaneously.

If you are installing with yarn, you can try listing both "arm64" and "x64"
in your ".yarnrc.yml" file using the "supportedArchitectures" feature:
https://yarnpkg.com/configuration/yarnrc/#supportedArchitectures
Keep in mind that this means multiple copies of esbuild will be present.

Another alternative is to use the "esbuild-wasm" package instead, which works
the same way on all platforms. But it comes with a heavy performance cost and
can sometimes be 10x slower than the "esbuild" package, so you may also not
want to do that.

Tentativas de resolução

Tentativa 1

Meu pensamento inicial foi: "Beleza, estou rodando num Mac M1, ele tem arquitetura arm64, vou seguir a sugestão proposta no erro, de criar um arquivo .yarnrc.yml com a propriedade supportedArchitectures."

Criei o arquivo, e adicionei a propriedade do mesmo jeito que estava exemplificado na doc do Yarn, agora vai!!
Rodei o comando pra iniciar a aplicação e... O MESMO ERRO.

Tentativa 2

Depois de mais algumas tentativas do jeito anterior, desisti de rodar localmente e pensei e dockerizar a aplicação, já que o Docker cria máquinas Linux, logo pensei que rodaria de primeira (ledo engano).
Descartando a configuração do Docker, que antes de funcionar ele te humilha um pouco kkk, quando fiz o build da máquina, foi retornado o mesmo erro basicamente, com alteração apenas nessa parte, que retornava algo assim:

Specifically the "@esbuild/darwin-arm64" package is present but this platform
needs the "@esbuild/linux-x64" package instead.

Com isso tentei forçar a arquitetura do container com PLATFORM=linux/x64no arquivo dockerfile da aplicação, e também no docker-compose.yml. Pra minha alegria, o erro que estava acontecendo antes já não aconteceu.
Mas foi retornado outro erro de que uma biblioteca não foi encontrada (sendo que ela estava no package.json e entrados nos arquivos do container, existia a pasta com os arquivos dentro da node_modules.
Pra resolver isso instalei a lib globalmente na máquina, e rodei de novo, daí um novo erro de que outras duas libs não tinham sido encontradas.
Daí eu desisti de dockerizar a aplicação e dei um tempo pra esfriar a cabeça (no caso fui dormir, porque já era 01:30 da manhã).

Enfim a resolução

Acordei no outro dia já pensando no problema e como poderia resolver, até tentei algumas coisas como mexer no arquivo yarn.lock, mas sem sucesso também. Daí fui atrás de outras maneiras de buildar a aplicação, já que com o Esbuild meu fim de semana de estudos estava indo por água abaixo.

Pesquisando por alternativas, encontrei dentro da página oficial de plugins da Serverless, um plugin chamado serverless-plugin-typescript (Link Oficial). E ele sim foi meu salvador... Então seguem os passos que tomei pra utilizar:

  1. Instalei o plugin como dependência de desenvolvimento (yarn add --dev serverless-plugin-typescript)
  2. Ajustei o arquivo serverless.ts (segue como o arquivo deve ficar):
import type { AWS } from '@serverless/typescript';

const serverlessConfiguration: AWS = {
  service: 'serverless',
  frameworkVersion: '3',
  
  // BASICAMENTE APENAS REMOVI O PLUGIN DO ESBUILD E COLOQUEI O QUE FOI BAIXADO
  plugins: ['serverless-plugin-typescript', 'serverless-offline'],
  
  provider: {
    name: 'aws',
    runtime: 'nodejs14.x',
    apiGateway: {
      minimumCompressionSize: 1024,
      shouldStartNameWithService: true,
    },
    environment: {
      AWS_NODEJS_CONNECTION_REUSE_ENABLED: '1',
      NODE_OPTIONS: '--enable-source-maps --stack-trace-limit=1000',
    },
  },
  
  functions: { 
    hello: {
      handler: "src/functions/hello.handler",
      events: [
        {
          http: {
            path: "hello",
            method: "get",
            cors: true
          }
        }
      ]
    }
  },
  package: { individually: true }
  
  // E REMOVI A CONFIGURAÇÃO CUSTOM QUE FICAVA NO FINAL DO ARQUIVO TAMBÉM
};

module.exports = serverlessConfiguration;
  1. Ajustei o arquivo tsconfig.json seguindo as especificações descritas na página do plugin:
{
  "compilerOptions": {
    "preserveConstEnums": true,
    "strictNullChecks": true,
    "sourceMap": true,
    "allowJs": true,
    "target": "es5",
    "outDir": ".build",
    "moduleResolution": "node",
    "lib": [
      "es2015"
    ],
    "rootDir": "./"
  }
}

Depois disso rodei o comando serverless offline pra testar, e correu tudo bem!!!

Aprendizados

Como disse no começo do artigo, essa brincadeira levou umas 8 horas entre sábado e domingo, então não estudei tanto Serverless como gostaria. Tá certo que eu me desafiei a resolver isso, porque não queria fazer downgrade das versões das libs (sabe-se lá se o erro não continuaria kkk), e foi legal esse desafio porque aprendi algumas coisas, por exemplo:

  • Resolução de Problemas: Durante o processo, acabou que não encontrei muita coisa sobre aquele primeiro erro relacionado ao Serverless, até vi pessoas que receberam ele, mas pra outras plataformas. O que me forçou a fuçar em funcionalidades e pensar em possíveis soluções pro problema, coisa que não aconteceria se já tivesse um abençoado no Stack Overflow ou GitHub falando sobre o problema.

  • Conhecimento Técnico: Aprendi coisas bem legais nesse processo a respeito do Docker, quando pesquisei como forçar a arquitetura do container. A respeito do Yarn e seu arquivo de configuração, dá pra configurar bastante coisa nele (depois deem uma olhada na documentação). E claro, sobre o Serverless, com seus plugins que da próxima vez vou passar por lá pra procurar ajuda antes de ficar 6 horas tentando resolver algo kkk.

  • Conhecimento Não Técnico: Uma coisa que tiro de lição pra quando estiver tentando resolver um erro, Bug ou algo do tipo é: Tire um tempo pra respirar e relaxar. Com certeza, ter ido dormir de sábado pra domingo, e uns 5 minutos aqui e ali pra tirar o erro do foco foram de ajuda. Quando fazemos isso, a mente se abre e tira da frente o erro, o que facilita pra pensar fora da caixinha e encontrar uma solução.

Por hoje é só pessoal... Espero que seja de ajuda pra alguém!
Se alguém quiser dar uma olhada no projeto, o link pro GitHub é esse aqui: artur-rod/serverless

Hoje (20/03/2023), o projeto ainda não está finalizado... mas logo vou finalizar e crio um README melhor pra ele!

Carregando publicação patrocinada...
2

É frustante quando tentamos iniciar um desenvolvimento em cima de algo novo (para nós) e as coisas começam assim. Esse tipo de problema afasta os iniciantes no mundo do desenvolvimento.

Por outro lado tentar resolver realmente é desafiador e ajuda a ter um entendimento maior de como as coisas funcionam, e dão booons "pontos de xp" para um desenvolvedor.

Recentemente decidi migrar um sistema que utiliza a Elasticsearh stack (ELK) para a versão opensource Opensearch, e encontrei tantos problemas por ser um projeto novo (a opensearch é um fork do elasticsearch antes da mudança na licença), tem muita coisa não documentada, os exemplos não funcionam como deveriam.

Isso me tirou muita produtividade, mas me fez entender bastante do ecossistema.

1

Isso é verdade, quando se está no começo realmente pode frustrar. Mas nisso já entra mais nas Soft Skills que são necessárias pra um bom programador, que é ter persistência também. Programação (e qualquer outra área) não é um mar de rosas onde tudo vai dar certo sempre.

Quanto mais profundo vai ficando nosso conhecimento, mais precisamos pensar fora da caixa e pensar em maneiras de solucionar algum problema.
Vai chegar um momento que a gente precisa resolver algo e não vai ter ninguém no StackOverflow pra ajudar kkk.