Pietrzak Roman
yosh.ke.mu
First version: 2016
Last changes: 2023-07-04
All rights reserved


2020 - 2023


ES6


Optimal JS, how V8 is built, V8 flags, memory optimization etc.


node.js and javascript in browser - good practices

Autorestarts

  • during development: nodemon. Don't manually kill and restart server for each iteration of code development.
  • for qa/production: forever - for simple, manual, 1-2 server deployments.
    For anything bigger, automate (docker + kubernetes is a good example, but not the only solution).
  • any form of live-reload instead of hitting F5:
    • Webpack dev server: when developing FE, it auto-compiles and auto-reloads in the background.
    • I mostly use the one which is a part of Kinession Framework, but there is plenty of choice of packages for each of your beloved frameworks: Angular, React, Vue - have their own development servers. Also Webpack has its own live-reload solution.

NPM

  • Enforce lockfile
  • Install in CI modemake sure you’re doing a clean install of your dependencies:
    npm ci
    It can be significantly faster than a regular npm install by skipping certain user-oriented features.
  • Install for production env:
    npm install --production
  • Read this: 10 npm Security Best Practices

Good OOP

KISS is king, OOP is another king, functional programming is one another king. :)
Prefer modular architecture, instead of monolith. But also learn what mono-repo is.
Don't reinvent the wheel - there is plenty of code packages for most of stuff you want to do. But don't be afraid of writing your own code - when what's available is just weak.
Forget false promises of "the only one framework" like Angular, React, Vue, etc.* - these will not solve a problem of NOT having architecture in your project.
* I'm not saying not to use them!
Callback hell ? Promises chasing other promises are "promises hell". Think about structure, design your code, log stuff, think again.

Functional, OOP and classes

For people coming from C++/Java/PHP/similar the main architectural entity is the class. It's important to understand, that class is considered as antipattern in JS as per 2017-2019. That's strongly opinionated thing, but JavaScript OOP is now encouraged by composition, instead of class-based architecture.
JavaScript's 1st citizen is Function, not class (yes, in ES6 too). Functional programming is king.
A lot of reading/watching below. if you're not convinced, watch/read even more - it's important to understand benefits of non-class based approach.

Good logs

Log a lot and often. Log EVERY error. Log every warning.
It's easier to get through good logs when something strange happened, than to investigate from "zero" point.
Don't safe too much of space - MBs and GBs of logs per day are managable.
I log witk K.Log as it logs with a good "context path" (machine->app->http_connection path), but there is plenty of libs.

Auto tests

Runner: Mocha.js, new kid in the block (2018) - Jest.js
Web testing: Selenium. If you need more stuff: karma.
Do not ignore tests, do not disable test - they are there for the reason, they make your development quicker, more agile. Skipping, ignoring, disabling - makes your test-suite aging fast, after some time making it unusuable.
Do not write too many tests - testing too obvious stuff makes developers slower not faster.
Do not write unit tests for what is not an unit: think twice if it's better to test a thing at the module level, or API level or UI level. It's rare case that you need them all.
Too many tests on too many layers - slow development. Not enough tests or stupid tests - slow development.

Links

CSS


About JS/GUI Frameworks

Some "psychology" of JavaScript

The concept of JavaScript fatigue - "Everything is amazing and nobody is happy."

General Web


General code


Some general node.js

npm install --global --production windows-build-tools

HTTPs/TLS, security certificates, encryption


Rendering to browser from node: Electron, Carlo

Carlo
Electron-gitbook

Using forever to run/restart/stop node.js server

This line is the main hint:
sudo forever -l log_production.log -o log_production.out -e log_production.err start -c "nodejs --max_old_space_size=300" production/src/run_production.js
this will run the server with 300MB limit for "old-space heap", and log stuff to "log_production" series of files.
WARNING: Look for max_old_space_size instead of max-old-space-size - which is advised in many old forums/stackoverflows etc.

Restarting and listing:
sudo forever list
this will show the list of uid-s of running forever-spawned processes. Pick a process and:
sudo forever restart <uid>
or
sudo forever stop <uid>


Deployment, containers, docker, Kubernetes (k8s)

"If you’re doing automation, you’re already doing something right. It’s not about how you do it."

HTML, CSS, Frontend libraries


Login, Authentication, Security


NPM, packages

npm and the Future of JavaScript by Laurie Voss from npm, Inc.

Transpiling

How to serve ES6 to modern browsers, and ES5 to old ones.

HTTP2

HTTP/2

CoffeeScript is dead

We loved CoffeeScript at some point and 99% of node.js/browser code we did in CS.
However, now with ES6 in place, the CS is a bit of dying thing.
Some thoughts:
  • The tool which is good enough to convert CoffeeScript to Javascript: https://github.com/decaffeinate/decaffeinate
    • return: it produces a lot of return statements at the end of functions which don't make sense - it's because of "functional" nature of CS
    • Array.from: in many/all for-loops which iterate over arrays it does Array.from(), which in many cases is useless and makes the code harder to read/optimise. And this breakes IE11
    • get the good thinking about ; (semicolons). We decided to have a loose policy - we mostly leave them in the code.
    • formatting of linebreaks around {} and few other formattings
    • an ugly hack for class constructors, where this code:
      constructor: (@x, @y) ->
        super()
      
      produces a lot, lot of noise JS code
  • Reading/editing CS is a big pleasure for us, while JS looks a lot more clunky
  • ES6 classess work well, the one missing point is static class variables (or class consts !)
  • we use a lot of namespacing for class names (react does it too ?)
    class K.somethingA extends K.somethingB
      ...code of the class...
    
    which doesn't work with ES6 classes.
    The ES6 pattern is ugly:
    K.SimpleObjectReadRemoteModel = class K_SimpleObjectReadRemoteModel extends K.Model
    {
      ...code of the class...
    }
    
  • we really miss @. I mean this:
    this.fieldA = this.fieldB + this.fieldC;
    
    comparing to this:
    @fieldA = @fieldB + @fieldC;
    
    when code is more advanced makes it a lot harder to read now...
  • we miss good existence operator
    It means this:
    if x?
      @set(x)
    
    is now
    if (typeof x !== 'undefined')
    {
      this.set(x);
    }
    
    In our Kinession framework we use "operators" on K.Object:
    K.isExistent(x)
    K.isNotNull(x)
    K.isNotEmptyString(x)
    K.isUndefined(x)
    
    However, still, writing CS code of:
    main?.instance?.of?.some?.class?.setVariable(x)
    
    is now a huge pain.

Libs, Frameworks, tools etc.


Other stuff

node-gyp and Python problems

If you haven't got python installed along with all the node-gyp dependencies, simply open Powershell or Git Bash with administrator privileges and execute:
npm install --global --production windows-build-tools

Bonus


Some code snippets

  • Node.js performance quick check:
    const { performance } = require('perf_hooks')
    const timings = {
      dataPoints: [],
      triggerDisplay: () => {
        setTimeout(() => {
            //console.log('timings:', timings.dataPoints)
            let stats = {
              sum: 0,
              cnt: 0
            }
            timings.dataPoints.forEach( (point) => {
              stats.sum += point
              stats.cnt++
            })
            stats.avg = stats.sum / stats.cnt
            //console.log(stats)
          },
          800
        )
      }
    }
     

Node.js: too many open files (on linux)

You see something like this:
Error: EMFILE: too many open files, watch...
and stack-trace mentions this:
at FSWatcher.start (internal/fs/watchers.js:169:26)

I'm using Ubuntu at the moment and running lot of visual studio code, nodemon and node.js instances at once.

Quick things to check:
  • limits per user, all things:
    ulimit -a
    or more specific - limits just for files:
    ulimit -n
  • general limits for processes in your system:
    prlimit
  • system settings (look for fs.* which relate to "file-system")
    sysctl -a
    or simply:
    $ sysctl -a | grep fs.file-max
    fs.file-max = 308115
    
  • Count open handles:
    sudo lsof | wc -l

Now depending on which limit you hit, different things to try...
  • Edit the following file
    /etc/security/limits.conf
    Add the following lines to it
    root soft     nproc          65535    
    root hard     nproc          65535   
    root soft     nofile         65535   
    root hard     nofile         65535
    

    (TODO - more on that later)



JavaScript failed !
So this is static version of this website.
This website works a lot better in JavaScript enabled browser.
Please enable JavaScript.