$30 off During Our Annual Pro Sale. View Details »

The Illustrated Guide to Node.js - KCDC 2023

The Illustrated Guide to Node.js - KCDC 2023

Node.js is a compelling platform for building all types of applications for startups to enterprises. Node.js strategically unites developers through the universal language of JavaScript. Or TypeScript! Why should you learn Node.js, and where do you start?

You will walk away from this fun introduction to Node.js having learned its strengths and the tools you need to be productive. We will cover a typical workflow of creating and debugging a web application. We'll also look at popular frameworks, libraries, and learning resources to give you the best start.

David Neal

June 22, 2023
Tweet

More Decks by David Neal

Other Decks in Technology

Transcript

  1. View Slide

  2. View Slide

  3. View Slide

  4. View Slide

  5. View Slide

  6. View Slide

  7. View Slide

  8. View Slide

  9. View Slide

  10. View Slide

  11. View Slide

  12. View Slide

  13. View Slide

  14. View Slide

  15. View Slide

  16. View Slide

  17. View Slide

  18. Why Node.js?
    • Rapid innovation & delivery
    • Developer happiness
    • Attract & retain talent
    • Performance
    “Why Node.js is Becoming the Go-To Technology in the Enterprise” – nearform.com

    View Slide

  19. Why Node.js?
    productivity
    satisfaction
    performance
    lower costs
    Improved results year-over-year
    Node.js Foundation User Survey

    View Slide

  20. View Slide

  21. View Slide

  22. View Slide

  23. • Backend API for SPAs, Mobile apps, etc.
    • “Serverless” computing
    • Real-time, streaming
    • WebSockets, push notifications
    • Chat, IM, social media
    Node.js Use Cases

    View Slide

  24. More than just backend
    • Automation Scripts (DevOps)
    • CLI tools (compile with nexe)
    • Microservices
    • Internet of Things
    • Desktop Apps

    View Slide

  25. Slack
    Visual Studio Code

    View Slide

  26. View Slide

  27. DevOps
    • Small footprint
    • Cross-platform
    • Event-driven
    • OSS tools
    • Containers

    View Slide

  28. View Slide

  29. View Slide

  30. View Slide

  31. View Slide

  32. View Slide

  33. View Slide

  34. Releases and Long-Term Support (LTS)

    View Slide

  35. View Slide

  36. View Slide

  37. View Slide

  38. Install Node.js
    https://nodejs.org

    View Slide

  39. Install Node.js with NVM
    Mac or Linux? Use nvm!
    https://github.com/nvm-sh/nvm
    Windows?
    Install Windows Subsytem for Linux (WSL)!
    > nvm install 18

    View Slide

  40. Install Node.js with NVM
    https://github.com/coreybutler/nvm-windows
    > nvm install 18

    View Slide

  41. What You Get
    > node –v
    v18.16.1
    > npm –v
    9.7.1

    View Slide

  42. > node –v
    v18.16.1
    > npm –v
    9.7.1
    What You Get

    View Slide

  43. First Things First!
    > mkdir myproject
    > cd myproject
    > npm init
    This utility will walk you through
    creating a package.json file...

    View Slide

  44. Install Dependencies
    > npm install axios
    > npm install --save-dev eslint
    > npm install -D eslint-config-reverentgeek

    View Slide

  45. const fs = require( "fs" ); // Built-in Node.js module
    const express = require( "express" ); // Module installed via npm
    const ApiService = require( "./app/ApiService" ); // Local module
    const api = new ApiService( { port: 8888 } );
    module-examples.js

    View Slide

  46. const fs = require( "fs" ); // Built-in Node.js module
    const express = require( "express" ); // Module installed via npm
    const ApiService = require( "./app/ApiService" ); // Local module
    const api = new ApiService( { port: 8888 } );
    module-examples.js

    View Slide

  47. const fs = require( "fs" ); // Built-in Node.js module
    const express = require( "express" ); // Module installed via npm
    const ApiService = require( "./app/ApiService" ); // Local module
    const api = new ApiService( { port: 8888 } );
    module-examples.js

    View Slide

  48. const fs = require( "fs" ); // Built-in Node.js module
    const express = require( "express" ); // Module installed via npm
    const ApiService = require( "./app/ApiService" ); // Local module
    const api = new ApiService( { port: 8888 } );
    module-examples.js

    View Slide

  49. const fs = require( "fs" ); // Built-in Node.js module
    const express = require( "express" ); // Module installed via npm
    const ApiService = require( "./app/ApiService" ); // Local module
    const api = new ApiService( { port: 8888 } );
    module-examples.js

    View Slide

  50. const ApiService = require( "./app/ApiService" );
    const api = new ApiService( { port: 8888 } );
    // Traditional Node-style callback
    api.methodWithACallback( "bacon", 42, function( err, results ) {
    if ( err ) {
    // Do something with the error
    console.log( err );
    return;
    }
    // Do stuff with results
    for ( let i = 0; i < results.length; i++ ) {
    // stuff...
    }
    } );
    callback-example.js

    View Slide

  51. const ApiService = require( "./app/ApiService" );
    const api = new ApiService( { port: 8888 } );
    // Traditional Node-style callback
    api.methodWithACallback( "bacon", 42, function( err, results ) {
    if ( err ) {
    // Do something with the error
    console.log( err );
    return;
    }
    // Do stuff with results
    for ( let i = 0; i < results.length; i++ ) {
    // stuff...
    }
    } );
    callback-example.js

    View Slide

  52. const ApiService = require( "./app/ApiService" );
    const api = new ApiService( { port: 8888 } );
    // Traditional Node-style callback
    api.methodWithACallback( "bacon", 42, function( err, results ) {
    if ( err ) {
    // Do something with the error
    console.log( err );
    return;
    }
    // Do stuff with results
    for ( let i = 0; i < results.length; i++ ) {
    // stuff...
    }
    } );
    callback-example.js

    View Slide

  53. const ApiService = require( "./app/ApiService" );
    const api = new ApiService( { port: 8888 } );
    // Promise-style callback
    api.methodReturningAPromise( "bacon", 42 )
    .then( results => {
    for ( let i = 0; i < results.length; i++ ) {
    // stuff...
    }
    } )
    .catch( err => {
    console.log( err );
    } );
    promise-example.js

    View Slide

  54. const ApiService = require( "./app/ApiService" );
    const api = new ApiService( { port: 8888 } );
    // Promise-style callback
    api.methodReturningAPromise( "bacon", 42 )
    .then( results => {
    for ( let i = 0; i < results.length; i++ ) {
    // stuff...
    }
    } )
    .catch( err => {
    console.log( err );
    } );
    promise-example.js

    View Slide

  55. const ApiService = require( "./app/ApiService" );
    const api = new ApiService( { port: 8888 } );
    // Promise-style callback
    api.methodReturningAPromise( "bacon", 42 )
    .then( results => {
    for ( let i = 0; i < results.length; i++ ) {
    // stuff...
    }
    } )
    .catch( err => {
    console.log( err );
    } );
    promise-example.js

    View Slide

  56. const ApiService = require( "./app/ApiService" );
    const api = new ApiService( { port: 8888 } );
    // Promise-style callback
    api.methodReturningAPromise( "bacon", 42 )
    .then( results => {
    for ( let i = 0; i < results.length; i++ ) {
    // stuff...
    }
    } )
    .catch( err => {
    console.log( err );
    } );
    promise-example.js

    View Slide

  57. const ApiService = require( "./app/ApiService" );
    const api = new ApiService( { port: 8888 } );
    // Async-await callback
    async function doTheThing() {
    try {
    const users = await api.asyncMethodReturningUsers();
    const results = await api.methodReturningAPromise( "bacon", 42 );
    for ( let i = 0; i < results.length; i++ ) {
    // stuff...
    }
    } catch( err ) {
    console.log( err );
    }
    }
    doTheThing();
    async-await-example.js

    View Slide

  58. const ApiService = require( "./app/ApiService" );
    const api = new ApiService( { port: 8888 } );
    // Async-await callback
    async function doTheThing() {
    try {
    const users = await api.asyncMethodReturningUsers();
    const results = await api.methodReturningAPromise( "bacon", 42 );
    for ( let i = 0; i < results.length; i++ ) {
    // stuff...
    }
    } catch( err ) {
    console.log( err );
    }
    }
    doTheThing();
    async-await-example.js

    View Slide

  59. const ApiService = require( "./app/ApiService" );
    const api = new ApiService( { port: 8888 } );
    // Async-await callback
    async function doTheThing() {
    try {
    const users = await api.asyncMethodReturningUsers();
    const results = await api.methodReturningAPromise( "bacon", 42 );
    for ( let i = 0; i < results.length; i++ ) {
    // stuff...
    }
    } catch( err ) {
    console.log( err );
    }
    }
    doTheThing();
    async-await-example.js

    View Slide

  60. const ApiService = require( "./app/ApiService" );
    const api = new ApiService( { port: 8888 } );
    // Async-await callback
    async function doTheThing() {
    try {
    const users = await api.asyncMethodReturningUsers();
    const results = await api.methodReturningAPromise( "bacon", 42 );
    for ( let i = 0; i < results.length; i++ ) {
    // stuff...
    }
    } catch( err ) {
    console.log( err );
    }
    }
    doTheThing();
    async-await-example.js

    View Slide

  61. function convertToCelsius( f ) {
    return ( f - 32 ) * ( 5 / 9 );
    }
    function convertToFahrenheit( c ) {
    return ( c * ( 9 / 5 ) ) + 32;
    }
    const temp = {
    freezingCelsius: 0,
    freezingFahrenheit: 32,
    boilingCelsius: 100,
    boilingFahrenheit: 212,
    convertToCelsius,
    convertToFahrenheit
    };
    module.exports = temp;
    temperature.js

    View Slide

  62. function convertToCelsius( f ) {
    return ( f - 32 ) * ( 5 / 9 );
    }
    function convertToFahrenheit( c ) {
    return ( c * ( 9 / 5 ) ) + 32;
    }
    const temp = {
    freezingCelsius: 0,
    freezingFahrenheit: 32,
    boilingCelsius: 100,
    boilingFahrenheit: 212,
    convertToCelsius,
    convertToFahrenheit
    };
    module.exports = temp;
    temperature.js

    View Slide

  63. function convertToCelsius( f ) {
    return ( f - 32 ) * ( 5 / 9 );
    }
    function convertToFahrenheit( c ) {
    return ( c * ( 9 / 5 ) ) + 32;
    }
    const temp = {
    freezingCelsius: 0,
    freezingFahrenheit: 32,
    boilingCelsius: 100,
    boilingFahrenheit: 212,
    convertToCelsius,
    convertToFahrenheit
    };
    module.exports = temp;
    temperature.js

    View Slide

  64. function convertToCelsius( f ) {
    return ( f - 32 ) * ( 5 / 9 );
    }
    function convertToFahrenheit( c ) {
    return ( c * ( 9 / 5 ) ) + 32;
    }
    const temp = {
    freezingCelsius: 0,
    freezingFahrenheit: 32,
    boilingCelsius: 100,
    boilingFahrenheit: 212,
    convertToCelsius,
    convertToFahrenheit
    };
    module.exports = temp;
    temperature.js

    View Slide

  65. function convertToCelsius( f ) {
    return ( f - 32 ) * ( 5 / 9 );
    }
    function convertToFahrenheit( c ) {
    return ( c * ( 9 / 5 ) ) + 32;
    }
    const temp = {
    freezingCelsius: 0,
    freezingFahrenheit: 32,
    boilingCelsius: 100,
    boilingFahrenheit: 212,
    convertToCelsius,
    convertToFahrenheit
    };
    module.exports = temp;
    temperature.js
    const t = require( "./temperature" );
    const c = t.boilingCelsius;
    const f = t.convertToFahrenheit( c );
    console.log( `${ c } C is ${ f } F` );
    // output: 100 C is 212 F
    temp-example.js

    View Slide

  66. function convertToCelsius( f ) {
    return ( f - 32 ) * ( 5 / 9 );
    }
    function convertToFahrenheit( c ) {
    return ( c * ( 9 / 5 ) ) + 32;
    }
    const temp = {
    freezingCelsius: 0,
    freezingFahrenheit: 32,
    boilingCelsius: 100,
    boilingFahrenheit: 212,
    convertToCelsius,
    convertToFahrenheit
    };
    module.exports = temp;
    temperature.js
    const t = require( "./temperature" );
    const c = t.boilingCelsius;
    const f = t.convertToFahrenheit( c );
    console.log( `${ c } C is ${ f } F` );
    // output: 100 C is 212 F
    temp-example.js

    View Slide

  67. function convertToCelsius( f ) {
    return ( f - 32 ) * ( 5 / 9 );
    }
    function convertToFahrenheit( c ) {
    return ( c * ( 9 / 5 ) ) + 32;
    }
    const temp = {
    freezingCelsius: 0,
    freezingFahrenheit: 32,
    boilingCelsius: 100,
    boilingFahrenheit: 212,
    convertToCelsius,
    convertToFahrenheit
    };
    module.exports = temp;
    temperature.js
    const t = require( "./temperature" );
    const c = t.boilingCelsius;
    const f = t.convertToFahrenheit( c );
    console.log( `${ c } C is ${ f } F` );
    // output: 100 C is 212 F
    temp-example.js

    View Slide

  68. function convertToCelsius( f ) {
    return ( f - 32 ) * ( 5 / 9 );
    }
    function convertToFahrenheit( c ) {
    return ( c * ( 9 / 5 ) ) + 32;
    }
    const temp = {
    freezingCelsius: 0,
    freezingFahrenheit: 32,
    boilingCelsius: 100,
    boilingFahrenheit: 212,
    convertToCelsius,
    convertToFahrenheit
    };
    module.exports = temp;
    temperature.js
    const t = require( "./temperature" );
    const c = t.boilingCelsius;
    const f = t.convertToFahrenheit( c );
    console.log( `${ c } C is ${ f } F` );
    // output: 100 C is 212 F
    temp-example.js

    View Slide

  69. function convertToCelsius( f ) {
    return ( f - 32 ) * ( 5 / 9 );
    }
    function convertToFahrenheit( c ) {
    return ( c * ( 9 / 5 ) ) + 32;
    }
    const temp = {
    freezingCelsius: 0,
    freezingFahrenheit: 32,
    boilingCelsius: 100,
    boilingFahrenheit: 212,
    convertToCelsius,
    convertToFahrenheit
    };
    module.exports = temp;
    temperature.js
    const t = require( "./temperature" );
    const c = t.boilingCelsius;
    const f = t.convertToFahrenheit( c );
    console.log( `${ c } C is ${ f } F` );
    // output: 100 C is 212 F
    temp-example.js

    View Slide

  70. import { readFile } from "node:fs/promises";
    export async function readFileJson( fileName ) {
    const text = await readFile( fileName );
    const data = JSON.parse( text );
    return data;
    }
    esm-module-example.js

    View Slide

  71. import { readFile } from "node:fs/promises";
    export async function readFileJson( fileName ) {
    const text = await readFile( fileName );
    const data = JSON.parse( text );
    return data;
    }
    esm-module-example.js

    View Slide

  72. import { readFile } from "node:fs/promises";
    export async function readFileJson( fileName ) {
    const text = await readFile( fileName );
    const data = JSON.parse( text );
    return data;
    }
    esm-module-example.js

    View Slide

  73. esm-module-example.js
    import { readFile } from "node:fs/promises";
    export async function readFileJson( fileName ) {
    const text = await readFile( fileName );
    const data = JSON.parse( text );
    return data;
    }
    esm-example.js
    import { readFileJson } from "./esm-module-example.mjs";
    const baconFile = new URL( "./bacon.json", import.meta.url );
    const bacon = await readFileJson( baconFile );
    console.log( bacon );

    View Slide

  74. esm-module-example.js
    import { readFile } from "node:fs/promises";
    export async function readFileJson( fileName ) {
    const text = await readFile( fileName );
    const data = JSON.parse( text );
    return data;
    }
    esm-example.js
    import { readFileJson } from "./esm-module-example.mjs";
    const baconFile = new URL( "./bacon.json", import.meta.url );
    const bacon = await readFileJson( baconFile );
    console.log( bacon );

    View Slide

  75. const sql = require( "mssql" );
    // Read from environment variables
    const cnx = process.env.SQL_CONNECTION;
    async function getAccountByEmail( email ) {
    try {
    const pool = await sql.connect( cnx );
    const result = await pool.request()
    .input( "email", sql.VarChar( 100 ), email )
    .query( "select * from accounts where email = @email" );
    return result;
    } catch ( err ) {
    // log error
    }
    }
    sql-example.js

    View Slide

  76. const sql = require( "mssql" );
    // Read from environment variables
    const cnx = process.env.SQL_CONNECTION;
    async function getAccountByEmail( email ) {
    try {
    const pool = await sql.connect( cnx );
    const result = await pool.request()
    .input( "email", sql.VarChar( 100 ), email )
    .query( "select * from accounts where email = @email" );
    return result;
    } catch ( err ) {
    // log error
    }
    }
    sql-example.js

    View Slide

  77. const sql = require( "mssql" );
    // Read from environment variables
    const cnx = process.env.SQL_CONNECTION;
    async function getAccountByEmail( email ) {
    try {
    const pool = await sql.connect( cnx );
    const result = await pool.request()
    .input( "email", sql.VarChar( 100 ), email )
    .query( "select * from accounts where email = @email" );
    return result;
    } catch ( err ) {
    // log error
    }
    }
    sql-example.js

    View Slide

  78. const sql = require( "mssql" );
    // Read from environment variables
    const cnx = process.env.SQL_CONNECTION;
    async function getAccountByEmail( email ) {
    try {
    const pool = await sql.connect( cnx );
    const result = await pool.request()
    .input( "email", sql.VarChar( 100 ), email )
    .query( "select * from accounts where email = @email" );
    return result;
    } catch ( err ) {
    // log error
    }
    }
    sql-example.js

    View Slide

  79. const sql = require( "mssql" );
    // Read from environment variables
    const cnx = process.env.SQL_CONNECTION;
    async function getAccountByEmail( email ) {
    try {
    const pool = await sql.connect( cnx );
    const result = await pool.request()
    .input( "email", sql.VarChar( 100 ), email )
    .query( "select * from accounts where email = @email" );
    return result;
    } catch ( err ) {
    // log error
    }
    }
    sql-example.js

    View Slide

  80. const sql = require( "mssql" );
    // Read from environment variables
    const cnx = process.env.SQL_CONNECTION;
    async function getAccountByEmail( email ) {
    try {
    const pool = await sql.connect( cnx );
    const result = await pool.request()
    .input( "email", sql.VarChar( 100 ), email )
    .query( "select * from accounts where email = @email" );
    return result;
    } catch ( err ) {
    // log error
    }
    }
    sql-example.js

    View Slide

  81. const sql = require( "mssql" );
    // Read from environment variables
    const cnx = process.env.SQL_CONNECTION;
    async function getAccountByEmail( email ) {
    try {
    const pool = await sql.connect( cnx );
    const result = await pool.request()
    .input( "email", sql.VarChar( 100 ), email )
    .query( "select * from accounts where email = @email" );
    return result;
    } catch ( err ) {
    // log error
    }
    }
    sql-example.js

    View Slide

  82. const sql = require( "mssql" );
    // Read from environment variables
    const cnx = process.env.SQL_CONNECTION;
    async function getAccountByEmail( email ) {
    try {
    const pool = await sql.connect( cnx );
    const result = await pool.request()
    .input( "email", sql.VarChar( 100 ), email )
    .query( "select * from accounts where email = @email" );
    return result;
    } catch ( err ) {
    // log error
    }
    }
    sql-example.js

    View Slide

  83. const sql = require( "mssql" );
    // Read from environment variables
    const cnx = process.env.SQL_CONNECTION;
    async function getAccountByEmail( email ) {
    ...
    }
    module.exports = {
    getAccountByEmail
    };
    sql-example.js

    View Slide

  84. View Slide

  85. View Slide

  86. View Slide

  87. Developer tools
    Package(s) Description
    eslint lint and format rules for JavaScript
    nodemon automatically restarts in dev
    node:test, jest, mocha test frameworks
    testdouble, sinon spies, stubs, mocks

    View Slide

  88. Recommended tools
    Package(s) Description
    dotenv loads environment variables from a .env file
    fs-extra adds convenient extensions to file system
    fetch, axios, or got http clients
    socket.io sockets, real-time
    commander command-line argument library for building CLIs
    nexe compile app to a standalone executable

    View Slide

  89. Frameworks
    • Express.js
    • Fastify
    • Nest.js
    • Electron.js

    View Slide

  90. Integration Strategies
    • Node.js as proxy, use http client
    • nginx
    • Messaging (e.g. RabbitMQ, ZeroMQ Azure
    Service Bus)

    View Slide

  91. https://bit.ly/node-crash-course

    View Slide

  92. View Slide

  93. View Slide

  94. View Slide