Exploring the New Features in Node.js Version 20 for Implementing Them in a Project
Tags: node, programming, javascript, webdev
Published: 2023-09-09 08:44:31

## Node.js v20+
Node.js v20, launched on April 18, 2023, introduces a range of exciting enhancements. In this release, Node.js focuses on bolstering its security by minimizing external dependencies and introducing a reliable built-in test runner. Moreover, Node.js v20 empowers developers to build self-contained executable applications that can run seamlessly on Windows, macOS, and Linux without the need for Node.js installation on users' systems.
In this post, we will be looking at some of the features of this improved version of Node.js and how to integrate them into your projects.

## Features in the Node.js v20
- Built-in .env file support
- Experimental Permission Model
- Custom ESM loader hooks on a dedicated thread
- Synchronous import.meta.resolve()
- url.parse() warns URLs with ports that are not numbers
- Stable test runner
- V8 JavaScript engine updated to V8 11.3

## Getting Started

- Download and Installation Node.js if it is not installed on your machine. 
- Use Node version Manager to upgrade your Node.js version if it is not v20. 

```javascript
nvm install v20.6.1
nvm use v20.6.1
```
- Initialize your node application with 

```javascript
npm init -y
```

## Built-in .env file support

## What is an environment variable

Environment variables provide insights into a process's operational context, encompassing aspects like production, development, and the build pipeline. In Node.js, they serve as a secure repository for sensitive information, such as passwords and API credentials, that should not be hard-coded in the codebase. Utilizing environment variables is essential for configuring variables or settings that may vary across different environments.

Node.js inherently supports environment variables, rendering them a superior choice compared to alternative configuration methods like config.js or config.json files. Leveraging environment variables, especially in tandem with automation tools like build pipelines, enables you to steer clear of cumbersome tasks like scripting configuration files.
One of the most popular package use in configuration of environment variable in node is the dotenv package but with the introduction of Node.js v20. Starting from Node.js v20.6.0, Node.js supports .env files for configuring environment variables.

Your configuration file should follow the INI file format, with each line containing a key-value pair for an environment variable. 

```javascript
URL = 'http://test.com'
```


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jmqx8t9pvpec4smz3riy.png)
To initialize your Node.js application with predefined configurations, use the following CLI command: 

```javascript
node --env-file=.env filename.js
```
. We can specific the folder in which the .env file is in 

```javascript
node --env-file=foldername/.env filename.js
```

We can go ahead and configure the package.json file to with above CLI command 

![Node 20 test](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1hvi3igwvknlqj5n8lpl.png)
We notice that this using nodemon package to turn our server.js file, this is useful for development purpose since it's watch for changes and restart the server if need be.

## Stable test runner

A test runner is a software tool or framework that automates the execution of tests for software applications. Its primary purpose is to locate, run, and report on the results of tests, making it an essential component of the software testing process. Test runners are particularly valuable in the context of automated testing and continuous integration (CI) pipelines. Here are some key aspects and functions of a test runner:

- Test Discovery: Test runners typically have the capability to discover and locate test cases within a codebase automatically. They can identify test files, classes, functions, or methods that are intended for testing.

- Execution: Test runners execute the identified tests, running them one by one or in parallel, depending on the configuration. They simulate the interaction with the application to verify that it behaves as expected.

- Reporting: Test runners collect and report the results of test execution. They provide information on which tests passed, which failed, and any errors or exceptions encountered during testing. This reporting helps developers identify and address issues in their code.

- Configuration: Test runners often allow configuration options to control how tests are executed. This includes specifying test environments, controlling parallelism, and filtering tests based on criteria like tags or categories.

- Integration: Test runners can be integrated into continuous integration (CI) and continuous delivery (CD) pipelines, enabling automated testing as part of the software development and deployment process. They can also integrate with other development tools and services.

- Support for Multiple Testing Frameworks: Many test runners are designed to work with various testing frameworks, such as JUnit, NUnit, Mocha, Jasmine, pytest, and more. This flexibility allows developers to choose the testing framework that best suits their project.

For Node.js we mostly used test runner like Jest or Mocha. With Node.js v20 we can now run tests without using external test runners. 

## Get started with Node Native Test
### The Node Test Module
The node:test module facilitates the creation of JavaScript tests. To access it:

```javascript
import test from 'node:test';
```
Tests created via the test module consist of a single function that is processed in one of three ways:

A synchronous function that is considered failing if it throws an exception, and is considered passing otherwise.
A function that returns a Promise that is considered failing if the Promise rejects, and is considered passing if the Promise resolves.
A function that receives a callback function. If the callback receives any truthy value as its first argument, the test is considered failing. If a falsy value is passed as the first argument to the callback, the test is considered passing. If the test function receives a callback function and also returns a Promise, the test will fail.

The Node.js v20 also exposes the assert module 

```javascript
import assert from 'node:assert'
```
Running tests can also be done using describe to declare a suite and it to declare a test. A suite is used to organize and group related tests together. it is a shorthand for test().

## Sample Test 

```javascript
import { describe, it } from 'node:test'
import assert from 'node:assert'
import { add, multiply, subtract } from '../calc.js'
describe('test', () => {
  it('should do some addition operation', () => {
    const result = add(2, 3)
    assert.equal(result, 5)
  })

  it('should do some subtraction operation', () => {
    const result = subtract(5, 3)
    assert.equal(result, 2)
  })

  it('should do some subtraction operation', { skip: true }, () => {
    const result = multiply(5, 3)
    assert.equal(result, 15)
  })
})

```

## The result of the test


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0f97opeigt5xqf4irblu.png)

We also have extra options for our test like
**Skipping tests**
Individual tests can be skipped by passing the skip option to the test, or by calling the test context's skip() method
**Only tests**
If Node.js is started with the --test-only command-line option, it is possible to skip all top level tests except for a selected subset by passing the only option to the tests that should be run.
**Filtering tests by name**
The --test-name-pattern command-line option can be used to only run tests whose name matches the provided pattern. Test name patterns are interpreted as JavaScript regular expressions.
That is it for now. See you in my next post