Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The Node.js Runtime Renaissance

Ruy Adorno
February 22, 2023

The Node.js Runtime Renaissance

Presented at ConFoo in Montreal, Canada on the February 22nd 2023.

Abstract: Last year was an exciting year for Node.js developers, with the arrival of refreshed competition the Node.js runtime has seen many new features landing under a renewed focus on developer experience. Learn more about what's new and how to use these new features today.

Ruy Adorno

February 22, 2023
Tweet

More Decks by Ruy Adorno

Other Decks in Programming

Transcript

  1. Ruy Adorno 
 Based in Montreal Node.js Collaborator & Releaser.

    
 Working with Node.js things at Google @[email protected] The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com
  2. Chronology 2022 features What’s next in 2023 ToC ConFoo 2023

    ruyadorno.com The Node.js Runtime Renaissance
  3. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com 2009 Ryan Dahl

    writes the initial implementation of the Node.js runtime
  4. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com 2018 Ryan Dahl

    announces the work on Deno, a new JavaScript runtime
  5. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com 2019 Node.js Foundation

    and the JS Foundation merge together forming the OpenJS Foundation
  6. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com The end of

    the small core Most collaborators these days are open to the idea of adding more features in order to provide a batteries-included experience in order to improve DX.
  7. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com Test Runner Shipped

    initially in v18.0.0, the test runner was initially designed to be a minimal viable test runner but has been getting more and more features since then.
  8. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com Test Runner -

    Mocks added in v18.13.0, v19.1.0 
 - Reporters added in v19.6.0 
 - Coverage added in v19.7.0 (this week!)
  9. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com import assert from

    'node:assert'; import test from 'node:test'; import {splitChars} from './split-chars.mjs'; test('test splitChars function', async t => { const input = 'a:b:c'; const expected = ['a', 'b', 'c']; assert.deepStrictEqual( splitChars(input), expected, 'should return expected characters' ); }) test-runner.mjs
  10. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com $ node test-runner.mjs

    TAP version 13 # Subtest: test splitChars function ok 1 - test splitChars function --- duration_ms: 4.859125 ... 1..1 # tests 1 # pass 1 # fail 0 # cancelled 0 # skipped 0 # todo 0 # duration_ms 59.869375 shell
  11. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com $ node --test

    TAP version 13 # Subtest: test splitChars function ok 1 - test splitChars function --- duration_ms: 4.859125 ... 1..1 # tests 1 # pass 1 # fail 0 # cancelled 0 # skipped 0 # todo 0 # duration_ms 59.869375 shell
  12. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com How the test

    runner finds what files to run - skip node_modules folders 
 - if a test folder is found, recursively fi nd all .js .cjs .mjs fi les 
 - in other folders, match: 
 - Files named test: ^test$ 
 - Filenames that start with test-: ^test-.+ 
 - Filenames that ends with -test: .+[\.\-\_]test$
  13. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com File Watcher First

    introduced in v18.11.0 and v16.19.0, the fi le watcher is a native way to have the node runtime reload anytime watched fi les are modi fi ed.
  14. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com import assert from

    'node:assert'; import test from 'node:test'; import {splitChars} from './split-chars.mjs'; test('test splitChars function', async t => { const input = 'a:b:c'; const expected = ['a', 'b', 'c']; assert.deepStrictEqual( splitChars(input), expected, 'should return expected characters' ); }) test-runner.mjs shell $ node --watch test-runner.mjs (node:42453) ExperimentalWarning: Watch mode is 
 an experimental feature and might change at any 
 time (Use `node --trace-warnings ...` to show where 
 the warning was created) TAP version 13 # Subtest: test splitChars function ok 1 - test splitChars function --- duration_ms: 2.681209 ... 1..1 # tests 1 # pass 1 # fail 0 # cancelled 0 # skipped 0 # todo 0 # duration_ms 6.377 Completed running 'test-runner.mjs'
  15. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com export function splitChars(str)

    { return str.split(':'); } split-chars.mjs shell $ node --watch test-runner.mjs (node:42453) ExperimentalWarning: Watch mode is 
 an experimental feature and might change at any 
 time (Use `node --trace-warnings ...` to show where 
 the warning was created) TAP version 13 # Subtest: test splitChars function ok 1 - test splitChars function --- duration_ms: 2.681209 ... 1..1 # tests 1 # pass 1 # fail 0 # cancelled 0 # skipped 0 # todo 0 # duration_ms 6.377 Completed running 'test-runner.mjs'
  16. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com export function splitChars(str)

    { return str.split('d'); } split-chars.mjs shell Restarting 'test-runner.mjs' TAP version 13 # Subtest: test splitChars function not ok 1 - test splitChars function --- duration_ms: 3.022458 failureType: 'testCodeFailure' error: 'should return expected characters' code: 'ERR_ASSERTION' 0: 'a' 1: 'b' 2: 'c' 0: 'a:b:c' operator: 'deepStrictEqual' ... 1..1 # tests 1 # pass 0 # fail 1 # duration_ms 6.597791 Failed running 'test-runner.mjs'
  17. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com export function splitChars(str)

    { return str.split(':'); } split-chars.mjs shell Restarting 'test-runner.mjs' TAP version 13 # Subtest: test splitChars function ok 1 - test splitChars function --- duration_ms: 2.054583 ... 1..1 # tests 1 # pass 1 # fail 0 # cancelled 0 # skipped 0 # todo 0 # duration_ms 4.697125 Completed running 'test-runner.mjs'
  18. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com More options -

    --watch-path specify what exact folders / fi les to watch, disable watching of imported modules 
 - --watch-preserve-output disable clearing the console when watch mode restarts the process
  19. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com Argument Parser Initially

    added in v18.3.0 and v16.17.0, the argument parser is an opinionated way to handle command line arguments in your apps without the need of an extra package.
  20. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com Argument Parser Made

    in collaboration between the maintainers of yargs and Commander , two of the most popular argument parsers.
  21. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com Argument Parser Currently

    an experimental API but should be promoted to stable soon. Unlikely to have changes at this point.
  22. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com import { parseArgs

    } from 'node:util'; const { values } = parseArgs({ options: { active: { type: 'boolean' }, pathname: { type: 'string' }, }, }); if (Object.keys(values).length) { console.table(values) } cli-parse-args.mjs
  23. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com $ node cli-parse-args.mjs

    --active \ --pathname=./cli-parse-args.mjs ┌──────────┬────────────────────────┐ │ (index) │ Values │ ├──────────┼────────────────────────┤ │ active │ true │ │ pathname │ './cli-parse-args.mjs' │ └──────────┴────────────────────────┘ shell
  24. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com Highly customizable The

    argument parser has much more options such as support to positional values, loose mode, providing default values, etc.
  25. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com Fetch After many

    years in the making, the fetch() method is fi nally available in Node.js starting at version v18.3.0 and up.
  26. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com const res =

    await fetch('https://nodejs.org/dist/index.json', { method: 'GET', headers: [ ['Accept', 'application/json'], ], }) const data = await res.json() const versions = data .map(i => ({ version: i.version, date: i.date })) .slice(0, 10) console.table(versions) fetch-something.mjs
  27. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com $ node fetch-something.mjs

    ┌─────────┬───────────┬──────────────┐ │ (index) │ version │ date │ ├─────────┼───────────┼──────────────┤ │ 0 │ 'v19.7.0' │ '2023-02-21' │ │ 1 │ 'v19.6.1' │ '2023-02-16' │ │ 2 │ 'v19.6.0' │ '2023-02-01' │ │ 3 │ 'v19.5.0' │ '2023-01-24' │ │ 4 │ 'v19.4.0' │ '2023-01-05' │ │ 5 │ 'v19.3.0' │ '2022-12-14' │ │ 6 │ 'v19.2.0' │ '2022-11-29' │ │ 7 │ 'v19.1.0' │ '2022-11-14' │ │ 8 │ 'v19.0.1' │ '2022-11-04' │ │ 9 │ 'v19.0.0' │ '2022-10-17' │ └─────────┴───────────┴──────────────┘ shell
  28. Stream iterator methods and Stream Web API helpers ConFoo 2023

    ruyadorno.com The Node.js Runtime Renaissance
  29. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com Stream iterator methods

    A variety of stream iterator methods have been introduced between v17.4.0 and v17.5.0. Some of these methods may also be available in v16.4.0.
  30. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com import { Readable

    } from 'node:stream'; const s = Readable.from([1, 2, 3, 4]); const mapped = [] s.on('data', data => { mapped.push(data * 2); }) s.on('end', () => { for (const m of mapped) { console.log(m) } }) map-stream-before.mjs map-stream-iterator.mjs import { Readable } from 'node:stream'; const s = Readable.from([1, 2, 3, 4]); const mapped = s.map(i => i * 2); for await (const m of mapped) { console.log(m); }
  31. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com Web Stream API

    Utility Consumers Added in v16.7.0, providing helper methods to help collect stream data.
  32. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com import { Readable

    } from 'node:stream'; const s = Readable .from(['a', 'b', 'c', 'd']); let res = ''; s.on('data', data => { res += data; }); s.on('end', () => { console.log(res); }); read-stream-before.mjs read-stream-utility-consumer.mjs import { Readable } from 'node:stream'; import { text } from 'node:stream/consumers'; const s = Readable .from(['a', 'b', 'c', 'd']); const res = await text(s); console.log(res);
  33. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com Web Stream API

    Utility Consumers There are also utility consumers for arrayBuffer , blob , buffer and json .
  34. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com Single Executable Apps

    (Just landed!) Added in v19.7.0, there’s now a way to package your app code along with the Node.js runtime so that you can distribute a single executable binary fi le.
  35. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com Process-based Permissions (Work

    in progress) New options to restrict access to speci fi c resources (such as fi le system, child process, workers) during execution.
  36. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com Process-based Permissions Very

    likely to still change, this new permission model is going to be behind a fl ag: --experimental-permission
  37. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com $ node --experimental-permission

    index.js node:internal/modules/cjs/loader:171 const result = internalModuleStat(filename); ^ Error: Access to this API has been restricted code: 'ERR_ACCESS_DENIED', permission: ‘FileSystemRead' $ node --experimental-permission --allow-fs-read=* --allow-fs-write=./tmp index.js Hello world! (node:19836) ExperimentalWarning: Permission is an experimental feature (Use `node --trace-warnings ...` to show where the warning was created) shell
  38. The Node.js Runtime Renaissance ConFoo 2023 ruyadorno.com Want to learn

    even more? Join one of the Working Groups meetings: https://nodejs.org/calendar 
 Join the OpenJS Foundation Slack: https://slack-invite.openjsf.org Repository: https://github.com/nodejs/node 
 Website: https://nodejs.org