Versão 20 NodeJS

O que há de novo na versão 20 do NodeJS ??

A versão 20 do Nodejs foi lançada em 18 de abril de 2023. Ela aborda alguns problemas e críticas já “resolvidos” por Deno e Bun, incluindo um novo modelo de permissão e um executor de testes nativo estável. Este artigo examina as novas opções disponíveis para desenvolvedores que usam o tempo de execução JavaScript mais usado no mundo.

O cronograma de lançamento do Node.js

  • As versões pares de abril (14, 16, 18, etc.) são estáveis ​​e recebem atualizações de suporte de longo prazo (LTS) por três anos.
  • Os lançamentos ímpares de outubro (15, 17, 19, etc.) são mais experimentais e as atualizações geralmente terminam após um ano.

Em geral, você deve optar pela versão LTS de número par, a menos que precise de um recurso específico em uma versão experimental e pretenda atualizar posteriormente. Dito isso, o Nodejs 20 é novo e o site recomenda que você continue com a versão 18 enquanto a equipe de desenvolvimento corrige quaisquer problemas recentes.

O Nodejs 20 tem os seguintes novos recursos…

Novo modelo de permissão

A execução do nó somescript.js não é isenta de riscos. Um script pode fazer qualquer coisa: excluir arquivos essenciais, enviar dados privados para um servidor ou executar um minerador de criptomoeda em um processo filho. É difícil garantir que seu próprio código não vai quebrar alguma coisa: você pode ter certeza de que todos os módulos e suas dependências estão seguros?

O novo modelo de permissão Nodejs (experimental) restringe o que o script pode fazer. Para usá-lo, adicione o sinalizador –experimental-permission à linha de comando do Nodejs seguido por:

  1. -allow-fs-read para conceder acesso de leitura aos arquivos. Você pode limitar o acesso de leitura a:
  • diretórios específicos: –allow-fs-read=/tmp/
  • arquivos específicos: –allow-fs-read=/home/me/data.json
  • ou padrões de arquivo curinga: –allow-fs-read=/home/me/*.json

2. –allow-fs-write para conceder acesso de gravação a arquivos com padrões idênticos de diretório, arquivo ou curinga.

3. –allow-child-process para permitir processos filhos, como a execução de outros scripts, talvez escritos em outras linguagens.

4. –allow-worker para permitir threads de trabalho, que executam o código Nodejs em paralelo ao thread de processamento principal.

No exemplo a seguir, somescript.js pode ler arquivos no diretório /home/me/data/:

node --experimental-permission --allow-fs-read=/home/me/data/ somescript.js

Qualquer tentativa de gravar um arquivo, executar outro processo ou iniciar um web worker gera um erro ERR_ACCESS_DENIED.

Você pode verificar as permissões em seu aplicativo usando o novo objeto process.permission. Por exemplo, veja como verificar se o script pode gravar arquivos:

process.permission.has('fs.write');

Veja como verificar se o script pode gravar em um arquivo específico:

if ( !process.permission.has('fs.write', '/home/me/mydata.json') ) {
  console.error('Cannot write to file');
}

O gerenciamento de permissão JavaScript foi introduzido pela primeira vez pelo Deno, que oferece controle refinado sobre o acesso a arquivos, variáveis de ambiente, informações do sistema operacional, medição de tempo, rede, bibliotecas carregadas dinamicamente e processos filhos. Node.js é inseguro por padrão, a menos que você adicione o sinalizador –experimental-permission. Isso é menos eficaz, mas garante que os scripts existentes continuem a ser executados sem modificações.

Curso Full Stack turbo - faça sua inscrição agora

Executor de teste nativo

Historicamente, o Nodejs tem um tempo de execução mínimo para que os desenvolvedores possam escolher quais ferramentas e módulos precisam. A execução de testes de código exigia um módulo de terceiros, como Mocha, AVA ou Jest. Embora isso tenha resultado em muitas opções, pode ser difícil tomar a melhor decisão, e a troca de ferramentas pode não ser fácil.

Outros tempos de execução adotaram uma visão alternativa e ofereceram ferramentas integradas consideradas essenciais para o desenvolvimento. Deno, Bun, Go e Rust oferecem executores de teste integrados. Os desenvolvedores têm uma escolha padrão, mas podem optar por uma alternativa quando seu projeto tiver requisitos específicos.

O Nodejs 18 introduziu um executor de teste experimental que agora está estável na versão 20. Não há necessidade de instalar um módulo de terceiros e você pode criar scripts de teste:

  • no diretório /test/ do seu projeto
  • nomeando o arquivo test.js, test.mjs ou test.cjs
  • usando test- no início do nome do arquivo – como test-mycode.js
  • usando teste no final do nome do arquivo com ponto anterior ( . ), hífen ( – ) ou sublinhado ( _ ) — como mycode-test.js, mycode_test.cjs ou mycode.test.mjs

Você pode então importar node:test e node:assert e escrever as funções de teste:

// test.mjs
import { test, mock } from 'node:test';
import assert from 'node:assert';
import fs from 'node:fs';

test('my first test', (t) => {
  assert.strictEqual(1, 1);
});

test('my second test', (t) => {
  assert.strictEqual(1, 2);
});

// asynchronous test with mocking
mock.method(fs, 'readFile', async () => 'Node.js test');
test('my third test', async (t) => {
  assert.strictEqual( await fs.readFile('anyfile'), 'Node.js test' );
});

Execute os testes com node –test test.mjs e examine a saída:

✔ my first test (0.9792ms)
✖ my second test (1.2304ms)
  AssertionError: Expected values to be strictly equal:

  1 !== 2

      at TestContext.<anonymous> (test.mjs:10:10)
      at Test.runInAsyncScope (node:async_hooks:203:9)
      at Test.run (node:internal/test_runner/test:547:25)
      at Test.processPendingSubtests (node:internal/test_runner/test:300:27)
      at Test.postRun (node:internal/test_runner/test:637:19)
      at Test.run (node:internal/test_runner/test:575:10)
      at async startSubtest (node:internal/test_runner/harness:190:3) {
    generatedMessage: false,
    code: 'ERR_ASSERTION',
    actual: 1,
    expected: 2,
    operator: 'strictEqual'
  }

✔ my third test (0.1882ms)
ℹ tests 3
ℹ pass 2
ℹ fail 1
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 72.6767

Você pode adicionar um sinalizador –watch para executar novamente os testes automaticamente quando o arquivo for alterado:

node --test --watch test.mjs

Você também pode executar todos os testes encontrados no projeto:

node --test

O teste nativo é uma adição bem-vinda ao tempo de execução do Node.js. Há menos necessidade de aprender diferentes APIs de terceiros e não tenho mais desculpa para esquecer de adicionar testes a projetos menores!

Compilando um único aplicativo executável

Os projetos Node.js requerem o tempo de execução para serem executados. Isso pode ser uma barreira ao distribuir aplicativos para plataformas ou usuários que não podem instalar ou manter facilmente o Node.js.

A versão 20 oferece um recurso experimental que permite criar um único aplicativo executável (SEA) que pode ser implantado sem dependências. O manual explica o processo, embora seja um pouco complicado:.

  • Você deve ter um projeto com um único script de entrada. Ele deve usar CommonJS em vez de Módulos ES.
  • Crie um arquivo de configuração JSON usado para criar seu script em um blob que é executado dentro do tempo de execução. Por exemplo, sea-config.json:
{
  "main": "myscript.js",
  "output": "sea-prep.blob"
}
  • Gere o blob com o node –experimental-sea-config sea-config.json.
  • De acordo com o seu sistema operacional, você deve copiar o executável do node, remover a assinatura do binário, injetar o blob no binário, assiná-lo novamente e testar o aplicativo resultante.

Embora funcione, você está limitado a projetos CommonJS mais antigos e só pode segmentar o mesmo sistema operacional que está usando. É certo que vai melhorar, já que o compilador Deno superior pode criar um executável para qualquer plataforma em um único comando a partir de arquivos de origem JavaScript ou TypeScript.

Você também deve estar ciente do tamanho do arquivo executável resultante. Um único console.log(‘Hello World’); gera um arquivo de 85 MB, porque o Node.js (e o Deno) precisam anexar todo o mecanismo V8 JavaScript e as bibliotecas padrão. Opções para reduzir o tamanho dos arquivos estão sendo consideradas, mas é improvável que fique abaixo de 25 MB.

A compilação não será prática para pequenas ferramentas de linha de comando, mas é uma opção mais viável para projetos maiores, como um aplicativo de servidor web completo.

Curso Full Stack turbo - faça sua inscrição agora

Mecanismo JavaScript V8 atualizado

O Node.js 20 inclui a versão mais recente do mecanismo V8, que inclui os seguintes recursos JavaScript:

  • String.prototype.isWellFormed(): retorna true quando uma string é bem formada e não contém caracteres substitutos solitários (não pareados).
  • String.prototype.toWellFormed(): retorna uma string bem formada que corrige problemas de caracteres substitutos solitários.
  • Um novo sinalizador v de expressão regular que aborda problemas com maiúsculas e minúsculas de caracteres Unicode.

Atualizações diversas

As seguintes atualizações e melhorias também estão disponíveis:

  • melhorias de desempenho para URL, fetch() nativo e APIs EventTarget
  • Melhorias no carregamento do módulo ES, incluindo suporte experimental para import.meta.resolve(), que pode definir o escopo de uma referência de caminho de arquivo do módulo para uma string de URL
  • Melhorias na interoperabilidade da Web Crypto API
  • Progresso adicional na WebAssembly System Interface (WASI), que concede acesso de aplicativos WASM em área restrita ao sistema operacional

Conclusão

O Nodejs 20 é um grande passo à frente. É um lançamento mais significativo e implementa alguns dos melhores recursos do Deno.

No entanto, isso levanta a questão: você deve usar o Deno?

Deno é ótimo. É estável, suporta TypeScript nativamente, reduz o tempo de desenvolvimento, requer menos ferramentas e recebe atualizações regulares. Por outro lado, já existe há menos tempo, tem menos módulos e geralmente são imitações mais superficiais das bibliotecas Node.js.

Vale a pena considerar Deno e Bun para novos projetos, mas existem milhares de aplicativos Node.js existentes. Deno e Bun estão facilitando a transição do código, mas nem sempre haverá uma clara vantagem em abandonar o Node.js.

A boa notícia é que temos um próspero ecossistema JavaScript. As equipes de tempo de execução estão aprendendo umas com as outras e a rápida evolução beneficia os desenvolvedores.

Conheça mais sobre o curso full stack turbo


Comentários

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *