guilima / financial-back

Node API structure connection to postgreSQL / redis
MIT License
4 stars 0 forks source link

Adicionar typescript no projeto #8

Closed guilima closed 4 years ago

guilima commented 4 years ago

Para me manter atualizado e acompanhando a evolução de outras linguagens, comecei um estudo de como implementar typescript em um projeto nodejs. Pontos importantes:

guilima commented 4 years ago
  1. Mudar todos os required para import. Necessário instalar dependência do typescript e seu executor/transpiler para node: ts-node. Além disso, precisa criar o arquivo tsconfig para compilar o código para js corretamente. Nele configurei:
    {
    "compilerOptions": {
      ...
      "outDir": "dist",
      "lib": ["ES2020"],
      "module": "CommonJS",
      "target": "ES2019",
      "moduleResolution": "node",
      "removeComments": true,
      "esModuleInterop": true
    },
    "include": [
      "index.ts",
      "update-monthly.scheduled.ts"
    ]
    }
    • "outDir": Diretório onde será colocado os arquivos na lista include, a partir daí a reação é em cadeia e todos os imports também vão juntos.
    • "target": Configuração da versão do ecmascript utilizado. Mantive sempre a próxima versão mais recente.
    • "lib": Configura as libs carregadas no projeto. Por default utiliza lista pré determinada do configurado no target. Nesse caso para evitar carregamento de outras libs adicionei apenas as features da versão mais recente do ecmascript, repetindo assim o valor do target.
    • "removeComments": Auto explicativo.
    • "esModuleInterop": Permiti que o transpiler do ts aceite modulos CommonJS (muitas dependências não pensam em atualizar tão cedo para o uso de import/export)
    • "module": Até a versão 12.11.0 do nodejs, configurar no package.json a propriedade type com valor module, apenas dava um warning ao executar o projetom, contudo após a atualização passou dar erro devido incompatibilidade com o que era selecionado nessa propriedade do tsconfig.
    • "moduleResolution": Possue valor default de acordo com o module, porém devido a inconsistência, recomendo adiciona-lo com valor "Node".

  1. Instalar libs @type para cada dependência, se existir. Demorou, mas finalmente todas as libs que utilizava no projeto aderiram ao @types. Por preferencia instalei-as como uma dependência dev.

  1. Configurar caminho absoluto dos arquivos importados. Abaixo está a configuração necessária:
    {
    "compilerOptions": {
      "baseUrl": ".",
      "paths": {
        "@business/*": ["src/business/*"],
        "@data/*": ["src/data/*"],
        "@middleware/*": ["src/middleware/*"],
        "@routes/*": ["src/routes/*"],
        "@schema/*": ["src/schema/*"],
        "@services/*": ["src/services/*"],
        "@util/*": ["src/util/*"],
        "*": ["node_modules/*"]
      },
      ...
    }

    Agora pensa numa configuração chata para os ambientes dev/prod funcionarem corretamente. É um combinação do que vai rodar no ambiente de desenvolvimento com o mapeamento dos nomes dos arquivos em tempo real (runtime). Em produção só muda que os arquivos precisam ter os nomes trocados em tempo de compilação (compiler).

guilima commented 4 years ago
  1. Ajustar ambiente dev com nodemon + typescript. Devido a necessidade de configuração do script de execução npm run debug para desenvolvimento local com auto reload foi utilizado a lib nodemon e criado o arquivo nodemon.json. No script de execução basta chamar nodemon que ele executa as configs no nodemon.json por padrão. Configuração:
    {
    "verbose": false,
    "debug": false,
    "exec": "node --inspect -r dotenv/config -r ts-node/register -r tsconfig-paths/register ./index.ts",
    "ignore": [
        "node_modules",
        "./test",
        "**/*.d.ts",
        "*.test.ts",
        "*.spec.ts",
        "fixtures/*",
        "test/**/*",
        "docs/*"
    ],
    "watch": ["./src"],
    "ext": "ts, gql"
    }

    Para rodar local com typescript além das variáveis de ambiente instalei a lib tsconfig-paths para que altere os caminhos absolutos dos arquivos importados. As propriedades não tem muito segredo por isso vou apenas detalher o valor encontrado na exec:

    • node -- inspect: Permiti inicialização do vscode launch e debug pela mesma ferramente
    • -r dotenv/config: Carrega modulo configurar as variáveis de ambientes, runtime
    • -r ts-node/register: Carrega modulo permite ler arquivos em typescript, runtime
    • -r tsconfig-paths/register: Carrega modulo permite alterar caminhos absolutos, runtime
    • ./index.ts: Arquivo a ser inicializado
guilima commented 4 years ago
  1. Ajustar ambiente prod para o build. Diferente do ambiente de desenvolvimento que temos apenas a inicialização da aplicação e atribuições em runtime, para produção a intenção é tornar o momento de inicialização e configurações em runtime o mais leve possível, para tal não se utilizou o ts-node nem tsconfig-paths. Unicamente utilizou-se o dotenv, pois é o momento mais oportuno para carregamento de variáveis de ambiente. O script npm run build: "tsc --project tsconfig.json && tscpaths -p tsconfig.json -s ."
    • tsc --project tsconfig.json: Do próprio typescript compila os arquivos seguindo as configurações indicados pelo parâmetro project, ou seja tsconfig.json. Por default o tsc já faz isso, apenas sendo usado explicitar.
    • &&: Em sequencia executar proxima ação.
    • tscpaths -p tsconfig.json -s .: Instalado dependência (caseira) tscpaths que utiliza configuração do tsconfig.json com source na raiz. Dessa forma no momento de compilar para .js os caminhos absolutos são trocados.

Após o momento de compilação completo é possível executar o script npm start: "node -r dotenv/config dist/index.js" Sobe servidor node pelo arquivo index, carregando antes o modulo de variáveis de ambiente.

guilima commented 4 years ago
  1. Tipagem do código e criação de interfaces. Foi realizado um trabalho parcial com métodos e variáveis simples. Contudo ainda deve tomar tempo para "tipar" tudo, já que essa issue se estendeu muito podemos realizar o merge da branch na master com as alterações.