with TypeScript
knowledge sharing for next project
not many good example in company repositories
work on best practices together
clean code -> cleaner tests -> cleanest project
Node Version Manager
> brew install nvm
> cat ~/.bash_profile
export NVM_DIR=~/.nvm
source $(brew --prefix nvm)/nvm.sh
> command -v nvm
> nvm --version
0.33.11
> cat ~/.nvmrc
v10.0.0NODE_VERSION=$(cat .nvmrc)
nvm cache clear
nvm install --latest-npm --lts $NODE_VERSION
nvm alias default $NODE_VERSION
nvm alias stable $NODE_VERSION
nvm use $NODE_VERSIONlong-term support all the way to ~2020
EcmaScript 2018 draft features support
asynchronous iteration and generators
rest/spread properties
Promise.finally
experimental EcmaScript modules instead of CommonJS
task managers (gulp) mostly unnecessary - use npm scripts
npm configuration for project through .npmrc
no global dependencies, use ./node_modules/.bin through scripts
# .npmrc
engine-strict = true # strict engine check
node-version = v10.0.0 # node version for strict engine check
save = true # update package.json after install/update
save-exact = true # update package.json with the given version
package-lock = true # create and update package-lock.json
# "scripts"
"initialize": "npm doctor && npm prune && npm cache verify && npm dedupe && npm ci",
development - build - production ready usage through docker
also working without docker through npm scripts
Makefile
Docker
npm scripts
.nvmrc
Codeship namespace is global, blocking builds, maybe Heroku CI?
.slugignore for Heroku (only useful assets deployed)
for proper dependency management
# "scripts"
"security:check": "nsp check --reporter minimal",
# .nsprc
{
"exceptions": [
"https://nodesecurity.io/advisories/566",
"https://nodesecurity.io/advisories/525"
]
}
# from NPM v6
"security:check": "npm audit",
not only a different language, but a tool
not the second CoffeeScript, 6 years history, increasing support
advanced type checking and definitions, also type inference
ES2018 target at the corner
any types, strange errors -> well-defined types, useful output
@types/* declaration packages are not unified quality
must keep @types/* packages sync with real ones
missing @types/* packages :(
But, easy to generate type declartions for packages now
{
"compilerOptions": {
"declaration": true,
"declarationDir": "./dist",
}
}tslib
reflect
sourcemap
compilation
for different purposes
# tsconfig.base.json
# tsconfig.test.json
# tsconfig.build.json
# tsconfig.json
{
"compilerOptions": {
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"strict": true,
"strictFunctionTypes": true,
"strictNullChecks": true,
"strictPropertyInitialization": true,
}
}
"watch": "rm -rf dist && tsc --project ./tsconfig.build.json --watch",
"build": "rm -rf dist && tsc --project ./tsconfig.build.json",import { ApplicationConfig, QueryParameters, ActionResponse, Logger, ActionParameters } from '../../../modules';
import { authDatabaseMiddleware } from '../../../middlewares';
import { ActionDescription } from '../../../decorators';
import { BaseAction } from '../../../models';
@ActionDescription({
method: 'GET',
path: '/api/accounts',
middlewares: [authenticationMiddleware],
})
export class AccountsAction implements BaseAction {
private _config: ApplicationConfig;
private _query: QueryParameters;
private _response: ActionResponse;
private _logger: Logger;
constructor({ config, query, response, logger }: ActionParameters) {
this._config = config;
this._query = query;
this._response = response;
this._logger = logger;
}
public async execute(): Promise<void> {
this._logger.success({ message: 'Ok' });
this._response.respondWithOk();
}
}
more deeper and stricter style checks because of TypeScript
TSLint is the "TypeScript-version" of ESLint
"code:style": "tslint --config ./tslint.json --format stylish --project ./tsconfig.json",
{
"rules": {
"no-unnecessary-type-assertion": [true],
"await-promise": [true],
"strict-boolean-expressions": [true],
}
}
Jasmine vs Tape vs Mocha
Mocha is the most configurable and reliable
Mocha has async support, helper modules preload, leak detection, etc
# .mocharc
--no-colors
--reporter spec
--require ts-node/register
--slow 100
--timeout 5000
--ui bdd
--check-leaks
--exit
--retries 5
--use_strict
easy API tests with supervisor
catch outgoing requests with nock
separate execution for integration and unit tests
describe(integration('Register Action'), () => {
context('when authentication cookie not posted', () => {
it('should respond with unauthorized', async () => {
return request(startApplication())
.post('/api/register')
.send({ user: 'stoiet' })
.expect(UNAUTHORIZED);
});
});
});describe(integration('Get Action'), () => {
it('should respond', context(({ suiteBackend }) => {
suiteBackend
.whenGET({ url: `campaigns/${CAMPAIGN_ID}` })
.thenRespondsWith({ subject: 'subject' });
}));
});
boar-server - not well maintained, really old
boar-koa-server - younger one, really thin layer
json-logger-js - not bad
boar-tasks/boar-tasks-server - horrible
AutoCannon - HTTP load benchmarking tool for NodeJS
Node-Clinic - diagnose NodeJS performance
0x - profiling tool for NodeJS