[comment]: # "markdown: { smartypants: true }" ### Navigating # Node.js #### in 2022
a (very opinionated) beginner's guide
![](https://coolaj86.com/assets/media/coolaj86-2017.jpg) AJ ONeal
[@\_beyondcode](https://twitter.com/@_beyondcode)
[twitch.tv/coolaj86](https://twitch.tv/coolaj86)
Technophobic Technologist Dangerous Wrong Thinker Equal Opportunity Offender
https://nodejs.org/en/about/resources/
!["node.js: too many cooks"](https://i.imgur.com/GIKXLBA.png)
!["classical learning curves"](https://i.imgur.com/RT2rUfV.png)
1. Why Node.js? 2. Install 3. Tools 4. Hello World 5. Web Server
When there's _great_ options out there...
https://go.dev/blog/go-brand
https://go.dev/blog/gopher
![](https://www.rust-lang.org/logos/rust-logo-256x256-blk.png)
https://github.com/rust-lang/rust/issues/11562
https://rustacean.net/
# 1. Why Node.js?
> "You're not paid to (ab)use _every_ feature of a language. > > You're paid to write _correct_ programs." ~ Douglas Crockford
### It is _possible_ ### to be # good ### at JavaScript
> "Perfection is achieved not when there is nothing more to add, > but when there is nothing left to take away" ~ Antoine de Saint-Exupery
# less ### is # more
# Benefits
- **Single-Threaded Execution** \ (no data races, like Rust)
- **Event-Oriented** \ (high concurrency, like Go)
- **Modern ALL-the-THINGS** \ (functional, duck-typed, pure-objects)
It's great for web services. ```js let server = express(); let app = Router(); server.use("/", app); Http.createServer(server).listen(3000); ```
https://www.npmjs.com/package/@root/async-router
And quite usable for command line utilities. ```js let { $, question, sleep } = await import("zx"); await $`ls -lah`; ```
https://github.com/google/zx
...
it's there
a lot
# Demerits
- **Too Much Legacy** \ (dumpster fire)
- **No Cohesion** \ (too many cooks)
...
- **Really, REALLY Bad Docs** \ (80/20 gone wrong)
Hold my MtnDew...
# 2. Install
## `sudo`
is _NOT_ your friend
## `PATH` is _NOT_ your friend
(and neither is `brew`)
`webi` is your friend ![](https://i.imgur.com/tlLp3NN.png)
- fastest (download) - fastest (setup) - conflict-free
and easy to remember ```sh curl "https://webinstall.dev" | bash webi node@lts ```
`+` cheat sheet ```bash webi node@latest ``` ```js let Http = require("http"); let app = function (req, res) { res.end("Hello, World!"); }; Http.createServer(app).listen(8080, function () { console.info("Listening on", this.address()); }); ```
# 3. Tools
Your brain is small.
And you suck at code.
(because you are human)
...
> "11 out of 10 dentists agree: > typing is the leading cause of typos" ~ ADA
# Tools 0. vim-essentials 1. prettier 2. jshint (or eslint) 3. jsdoc 4. tsc
## vim-essentials ```bash webi vim-essenntials ```
## vim learn how to use the computer already
(are you back-end or not?)
## VS Code an acceptable alternative
### Spot Check How beginner are we?
- functions - events - primitives - variables - Promises - RegExp
- require - process - module scope - Fs - Buffer
## Prettier
0 BS
## Prettier ```bash webi prettier ``` ```bash npm install -g prettier ```
## Prettier `package.json`: ```bash { "scripts": { "prettier": "npx prettier@2.x -w '**/*.{md,js,html,css}'" } } ``` ```bash npm run prettier ```
## jshint
> "jslint has taught me more than I ever taught it" ~ Douglas Crockford
## jshint ```bash webi jshint ``` ```bash npm install -g jshint ```
## jshint `package.json`: ```json { "scripts": { "lint": "npx jshint@2.x -c ./.jshintrc *.js */*.js" } } ``` ```bash npm run lint ```
## vs eslint also good, but not as simple
## jsdoc ```bash npm install -g jsdoc ``` (for type hinting)
## jsdoc ```js /** * Starts the important thing with the stuff * @namespace Service * @param {Object} opts - all of the options * @param {String} opts.units - either 'meters' or 'feet' * @returns {Promise
} - the process id */ Service.start = async function (opts) { // ... }; ```
## jsdoc `package.json`: ```json { "scripts": { "doc": "npx jsdoc@3.x --configure ./jsdoc.conf.json --destination ./docs --package ./package.json --readme ./README.md --access all --private --recurse ./index.js ./lib/" } } ``` ```bash npm run doc ```
## tsc ```bash npm install -g typescript ``` (for type hinting)
```js let answer = "Hello, World!"; answer = 42; // ❌ number is not a string ```
```js let Widget = require("widget"); Widget.getGizmo(); // ❌ did you mean getGadget()? ```
https://github.com/BeyondCodeBootcamp/jsdoc-typescript-starter
# et cetera
## Why not Co-Pilot?
# 🚽
(you'll write enough bad code all on your own)
## 4. Hello World ```js console.info("Hello, World!"); ```
(console.log is for burning)
A better hello world... - a useful function - a unit test - an export - an import - a package
```js function greet(person) { return `Hello, ${person.name}!`; } ``` ❌ not useful
`messenger.js` ```js "use strict"; let Messenger = module.exports; ```
`module` `module.exports`
(🤯 don't overwrite `module.exports`!)
```js Messenger.parseEmails = function (text) { let emailRe = /[\w\.+-]+@[a-z][0-9a-z-\.]+[a-z]/gi; let emails = {}; for (;;) { let m = emailRe.exec(text); if (!m) { break; } let email = m[0].toLowerCase(); emails[email] = true; } return Object.keys(emails); }; ``` just trust me...
```js regexp.exec; ``` ```js for (;;) ``` ```js Object.keys; ```
Some sample input... ```txt Hello, my email is coolaj86@gmail.com. I like long messages from walks@beach.co coolaj86+node.js@gmail.com is an alias of mine. ```
A little self-test... ```js if (require.main === module) { let Assert = require("assert"); let text = ` Hello, my email is coolaj86@gmail.com. I like long messages from walks@beach.co `; let expected = "coolaj86@gmail.com,walks@beach.co,coolaj86+node.js@gmail.com"; let emails = Messenger.parseEmails(text).join(","); Assert.equal(expected, emails); console.info("Pass"); // ✅ "Pass" } ```
```js require; ``` ```js require.main; ``` ```js Assert; ```
how to use in multiple files?
`bin/parse-emails.js` ```js #!/usr/bin/env node "use strict"; let Messenger = require("./messenger.js"); let text = process.argv.slice(2).join(" "); let emails = Messenger.parseEmails(text); emails.forEach(function (email) { console.info(email); }); ``` ```bash chmod a+x bin/parse-emails.js ln -s parse-emails.js bin/parse-emails ```
```js #!/usr/bin/env node ``` ```js chmod; ``` ```js ln - s; ```
How to share with others?
## npm
https://gist.github.com/coolaj86/1318304
```bash npm config set init.author.email "you@example.com" ``` ```bash npm adduser ``` ```bash npm publish --access=public @YOUR_NAME/messenger ```
## 5. SaaS-ify
`server.js` ```js let Http = require("http"); let httpServer = require("http").createServer(app); httpServer.listen(3000, function () { console.info("Listening on", httpServer.address()); }); ```
```js function app(req, res) { let text = ""; req.on("readable", function () { for (;;) { let chunk = req.read()?.toString("utf8"); if (!chunk) { break; } text += chunk; } }); req.on("end", function () { let emails = Messenger.parseEmails(text).join(","); res.end(emails); }); }); ```
```js Http.createServer(app); ``` ```js req.on("readable"); ```
```bash npm run start ```
# Bonus Round
## telebit
## caddy + duckdns ```caddy example.duckdns.org { tls { dns duckdns xxxxxxxx-xxxx-4xxx-8xxx-xxxxxxxxxxxx } log { output stdout format console } reverse_proxy /api/* localhost:3000 root * /srv/example.com/public/ file_server } ```
> "if you use all of your intelligence to build the most complex thing you can, given there's a defect in there, by definition it's more complex than you can understand" ~ [Darryl Spencer](https://www.youtube.com/watch?v=OYMk4Zws-jE&t=3732s) ~ [Darryl Spencer](https://www.youtube.com/watch?v=OYMk4Zws-jE&t=3732s)